remove all code for "parent" / "child" handling

It's not used (and therefore not real-life-tested) anywhere and current implementation is known to be partial and a bit hard to maintain.

authorAdrien Di Mascio <Adrien.DiMascio@logilab.fr>
changeset98252caba3b8
branchdefault
phasedraft
hiddenyes
parent revision#50c35d049616 [hook] move delete es document in method and catch not found error
child revision#873048fa96c9 [tests] Person must have fti fields in order to be indexed
files modified by this revision
cubicweb_elasticsearch/entities.py
cubicweb_elasticsearch/search_helpers.py
cubicweb_elasticsearch/testutils.py
cubicweb_elasticsearch/views.py
test/test_hooks.py
test/test_parents.py
# HG changeset patch
# User Adrien Di Mascio <Adrien.DiMascio@logilab.fr>
# Date 1492098551 -7200
# Thu Apr 13 17:49:11 2017 +0200
# Node ID 98252caba3b8869aafbf67512c5f95176f71c672
# Parent 50c35d049616db311e62ca0977bff59055400210
remove all code for "parent" / "child" handling

It's not used (and therefore not real-life-tested) anywhere
and current implementation is known to be partial and a bit
hard to maintain.

diff --git a/cubicweb_elasticsearch/entities.py b/cubicweb_elasticsearch/entities.py
@@ -97,21 +97,13 @@
1              'cw_etype': entity.cw_etype,
2              'eid': entity.eid,
3              'cwuri': entity.cwuri,
4          }
5          data.update(entity.cw_attr_cache)
6 -        self.update_parent_info(data, entity)
7          # TODO take a look at what's in entity.cw_relation_cache
8          return data
9 
10 -    def update_parent_info(self, data, entity):
11 -        """this is where a client cube would feed the 'parent' index
12 -
13 -            data['parent'] = entity.entry_of[0]
14 -        """
15 -        pass
16 -
17 
18  class File(IFullTextIndexSerializable):
19      __select__ = IFullTextIndexSerializable.__select__ & is_instance('File')
20 
21      def serialize(self, complete=False):
diff --git a/cubicweb_elasticsearch/search_helpers.py b/cubicweb_elasticsearch/search_helpers.py
@@ -19,13 +19,11 @@
22 
23  from logilab.mtconverter import xml_escape
24 
25 
26  def compose_search(search, query=None, fields=(),
27 -                   fuzzy=False, parents_for=None,
28 -                   phrase=True, common=True,
29 -                   children_for=None):
30 +                   fuzzy=False, phrase=True, common=True):
31      '''
32      Compose a elasticsearch-dsl query from queries :
33 
34      * simple term
35      * simple terms (OR)
@@ -41,14 +39,10 @@
36      fields:
37          restrict and boost search on certain fields eg. ('title^2', '_all')
38      fuzzy:
39          add a fuzzy search element to part of the query generated
40          https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html
41 -    parents_for:
42 -        additionnally search to get the parents for a given type
43 -    children_for:
44 -        restrict search to get the children of a given stable_id
45      '''
46      # FIXME TODO - restructure entier code base, have a proper lexer
47      for char in ('"', "'", xml_escape('"'), xml_escape("'")):
48          # TODO - implement phrase + term
49          if len(query.split(char)) == 3:
@@ -102,21 +96,10 @@
50                                fields=fields))
51 
52          else:
53              if fuzzy:
54                  should.append(dsl_query.Fuzzy(_all=element))
55 -    # TODO - careful with explain for performance reasons, maybe skip if nb terms < 3
56 -    if children_for:
57 -        match_stable_id = dsl_query.Match(stable_id=children_for)
58 -        must.append(dsl_query.HasParent(type="FindingAid",
59 -                                        score_mode="score",
60 -                                        query=match_stable_id))
61 -    if parents_for:
62 -        has_child = dsl_query.HasChild(type=parents_for,
63 -                                       score_mode="sum",
64 -                                       query=phrase_query)
65 -        should.append(has_child)
66      bool_query = dsl_query.Bool(must=must,
67                                  must_not=must_not,
68                                  should=should,
69                                  minimum_should_match=minimum_should_match)
70      search.query = bool_query
diff --git a/cubicweb_elasticsearch/testutils.py b/cubicweb_elasticsearch/testutils.py
@@ -1,27 +1,16 @@
71  import unittest
72  import httplib
73 
74  from elasticsearch_dsl.connections import connections
75 
76 -from cubicweb.predicates import is_instance
77 -
78  from cubicweb_elasticsearch.es import CUSTOM_ATTRIBUTES
79 -from cubicweb_elasticsearch.entities import IFullTextIndexSerializable
80 
81 
82  CUSTOM_ATTRIBUTES['Blog'] = ('title',)
83 
84 
85 -class BlogFTIAdapter(IFullTextIndexSerializable):
86 -    __select__ = (IFullTextIndexSerializable.__select__ &
87 -                  is_instance('BlogEntry'))
88 -
89 -    def update_parent_info(self, data, entity):
90 -        data['parent'] = entity.entry_of[0].eid
91 -
92 -
93  class RealESTestMixin(object):
94 
95      @classmethod
96      def setUpClass(cls):
97          try:
diff --git a/cubicweb_elasticsearch/views.py b/cubicweb_elasticsearch/views.py
@@ -44,24 +44,20 @@
98 
99      def __init__(self, query=None,
100                   filters={},
101                   doc_types=None,
102                   index=None,
103 -                 parents_for=None,
104 -                 children_for=None,
105                   form=None,
106                   **kwargs):
107          if index:
108              self.index = index
109          if doc_types:
110              self.doc_types = doc_types
111          if form:
112              self.form = form
113          else:
114              self.form = {}
115 -        self.parents_for = parents_for
116 -        self.children_for = children_for
117          self.extra_kwargs = kwargs
118          super(CWFacetedSearch, self).__init__(query, filters)
119 
120      def query(self, search, query):
121          if query:
@@ -71,13 +67,11 @@
122              return compose_search(search,
123                                    query=query,
124                                    fields=self.fields,
125                                    fuzzy=fuzzy,
126                                    common=common,
127 -                                  phrase=phrase,
128 -                                  parents_for=self.parents_for,
129 -                                  children_for=self.children_for)
130 +                                  phrase=phrase)
131          return search
132 
133      def highlight(self, search):
134          """
135          Add custom highlighting
@@ -103,30 +97,23 @@
136 
137      def do_search(self, query_string):
138          get_connection(self._cw.vreg.config)
139          facet_selections = {}
140          start, stop = 0, 10
141 -        parents_for = children_for = None
142          for key, value in self._cw.form.items():
143              if key.startswith('es_'):
144                  # FIXME TODO have better typing mechanisme (inspect facets?)
145                  try:
146                      facet_selections[key.replace('es_', '')] = int(value)
147                  except ValueError:
148                      facet_selections[key.replace('es_', '')] = value
149 -            if key == 'parents_for':
150 -                parents_for = value
151 -            if key == 'children_for':
152 -                children_for = value
153              if key == 'page':
154                  start = (max(int(value) - 1, 0)) * 10
155                  stop = start + 10
156          search = self.customize_search(query_string,
157                                         facet_selections,
158 -                                       start, stop,
159 -                                       parents_for=parents_for,
160 -                                       children_for=children_for)
161 +                                       start, stop)
162          if 'debug-es' in self._cw.form:
163              import json
164              self.w(u'<pre>')
165              self.w(unicode(json.dumps(search._s.to_dict(), indent=2)))
166              self.w(u'</pre>')
diff --git a/test/test_hooks.py b/test/test_hooks.py
@@ -1,18 +1,12 @@
167  import unittest
168 -import time
169 
170  from mock import patch
171 
172 -from elasticsearch_dsl import Search
173 -
174  from cubicweb.devtools import testlib
175  from cubicweb.cwconfig import CubicWebConfiguration
176 
177 -from cubicweb_elasticsearch.testutils import RealESTestMixin, BlogFTIAdapter
178 -from cubicweb_elasticsearch.search_helpers import compose_search
179 -
180 
181  class IndexHookTC(testlib.CubicWebTC):
182 
183      def setup_database(self):
184          super(IndexHookTC, self).setup_database()
@@ -36,49 +30,7 @@
185              args, kwargs = es.index.call_args
186              for arg_name, expected_value in (('id', p.eid), ('doc_type', p.cw_etype)):
187                  self.assertEqual(kwargs[arg_name], expected_value)
188 
189 
190 -class ReindexOnRelationTests(RealESTestMixin, testlib.CubicWebTC):
191 -
192 -    def test_es_hooks_modify_relation(self):
193 -        with self.admin_access.cnx() as cnx:
194 -            with self.temporary_appobjects(BlogFTIAdapter):
195 -                indexer = cnx.vreg['es'].select('indexer', cnx)
196 -                indexer.create_index(custom_settings={
197 -                    'mappings': {
198 -                        'BlogEntry': {'_parent': {"type": "Blog"}},
199 -                    }
200 -                })
201 -                blog1 = cnx.create_entity('Blog', title=u'Blog')
202 -                entity = cnx.create_entity('BlogEntry',
203 -                                           title=u'Article about stuff',
204 -                                           content=u'yippee',
205 -                                           entry_of=blog1)
206 -                blog2 = cnx.create_entity('Blog', title=u'Blog')
207 -                cnx.commit()
208 -                time.sleep(2)  # TODO find a way to have synchronous operations in unittests
209 -                search = compose_search(Search(index=self.config['index-name'],
210 -                                               doc_type='Blog'),
211 -                                        'yippee',
212 -                                        parents_for="BlogEntry",
213 -                                        fields=['_all'])
214 -                results = search.execute()
215 -                self.assertEquals(len(results), 1)
216 -                self.assertCountEqual([hit.eid for hit in results],
217 -                                      [blog1.eid])
218 -                blog2.cw_set(reverse_entry_of=entity)
219 -                cnx.commit()
220 -                time.sleep(2)  # TODO find a way to have synchronous operations in unittests
221 -                search = compose_search(Search(index=self.config['index-name'],
222 -                                               doc_type='Blog'),
223 -                                        'yippee',
224 -                                        parents_for="BlogEntry",
225 -                                        fields=['_all'])
226 -                results = search.execute()
227 -                self.assertEquals(len(results), 2)
228 -                self.assertCountEqual([hit.eid for hit in results],
229 -                                      [blog1.eid, blog2.eid])
230 -
231 -
232  if __name__ == '__main__':
233      unittest.main()
diff --git a/test/test_parents.py b/test/test_parents.py
@@ -1,55 +0,0 @@
234 -from __future__ import print_function
235 -
236 -import time
237 -import unittest
238 -
239 -from elasticsearch_dsl import Search
240 -
241 -from cubicweb.devtools import testlib
242 -
243 -from cubicweb_elasticsearch.search_helpers import compose_search
244 -
245 -from cubicweb_elasticsearch.testutils import RealESTestMixin, BlogFTIAdapter
246 -
247 -
248 -class ParentsSearchTC(RealESTestMixin, testlib.CubicWebTC):
249 -
250 -    def test_parent_search(self):
251 -        with self.admin_access.cnx() as cnx:
252 -            with self.temporary_appobjects(BlogFTIAdapter):
253 -                indexer = cnx.vreg['es'].select('indexer', cnx)
254 -                indexer.create_index(custom_settings={
255 -                    'mappings': {
256 -                        'BlogEntry': {'_parent': {"type": "Blog"}},
257 -                    }
258 -                })
259 -                test_structure = {
260 -                    u'A': [u'Paris ceci', u'Nantes', u'Toulouse'],
261 -                    u'B': [u'Paris cela'],
262 -                    u'C': [u'Paris autre', u'Paris plage'],
263 -                }
264 -                for fa_title, facomp_contents in test_structure.items():
265 -                    blog = cnx.create_entity('Blog',
266 -                                             title=fa_title)
267 -                    for facomp_content in facomp_contents:
268 -                        cnx.create_entity('BlogEntry',
269 -                                          entry_of=blog,
270 -                                          title=facomp_content,
271 -                                          content=facomp_content)
272 -                cnx.commit()
273 -            time.sleep(2)  # TODO find a way to have synchronous operations in unittests
274 -            for query, number_of_results, first_result in (("Paris", 3, "C"),
275 -                                                           ("Nantes", 1, "A")):
276 -                search = compose_search(Search(index=self.config['index-name'],
277 -                                               doc_type='Blog'),
278 -                                        query,
279 -                                        parents_for="BlogEntry",
280 -                                        fields=['_all'],
281 -                                        fuzzy=True)
282 -                self.assertEquals(len(search.execute()), number_of_results)
283 -                self.assertEquals(search.execute().to_dict()['hits']['hits'][0]['_source']['title'],
284 -                                  first_result)
285 -
286 -
287 -if __name__ == '__main__':
288 -    unittest.main()