@@ -22,56 +22,110 @@ class NestedQueryBackend(BaseSearchQueryBackend):
2222 def construct_search (cls , request , view , search_backend ):
2323 """Construct search.
2424
25+ Dictionary key is the GET param name. The path option stands for the
26+ path in Elasticsearch.
27+
28+ Type 1:
29+
30+ search_nested_fields = {
31+ 'country': {
32+ 'path': 'country',
33+ 'fields': ['name'],
34+ },
35+ 'city': {
36+ 'path': 'country.city',
37+ 'fields': ['name'],
38+ },
39+ }
40+
41+ Type 2:
42+
43+ search_nested_fields = {
44+ 'country': {
45+ 'path': 'country',
46+ 'fields': [{'name': {'boost': 2}}]
47+ },
48+ 'city': {
49+ 'path': 'country.city',
50+ 'fields': [{'name': {'boost': 2}}]
51+ },
52+ }
53+
2554 :param request:
2655 :param view:
2756 :param search_backend:
2857 :return:
2958 """
59+ if not hasattr (view , 'search_nested_fields' ):
60+ return []
61+
3062 query_params = search_backend .get_search_query_params (request )
3163 __queries = []
64+
3265 for search_term in query_params :
3366 __values = search_backend .split_lookup_name (search_term , 1 )
3467 __len_values = len (__values )
3568 if __len_values > 1 :
36- field , value = __values
37- if field in view .search_nested_fields :
38- # Initial kwargs for the nested query
39- field_kwargs = {field : {'query' : value }}
40- # In case if we deal with structure 2
41-
42- extra_field_kwargs = view .search_nested_fields [field ]
43- if extra_field_kwargs :
44- field_kwargs [field ].update (extra_field_kwargs )
45- path = extra_field_kwargs .pop ('path' )
46-
47- # The match query
69+ label , value = __values
70+ if label in view .search_nested_fields :
71+ options = view .search_nested_fields .get (label )
72+ path = options .get ('path' )
73+
74+ queries = []
75+ for _field in options .get ('fields' , []):
76+ # In case if we deal with structure 2
77+ if isinstance (_field , dict ):
78+ # TODO: take options (ex: boost) into consideration
79+ field = "{}.{}" .format (path , _field ['name' ])
80+ # In case if we deal with structure 1
81+ else :
82+ field = "{}.{}" .format (path , _field )
83+
84+ field_kwargs = {
85+ field : value
86+ }
87+
88+ queries = [
89+ Q ("match" , ** field_kwargs )
90+ ]
91+
4892 __queries .append (
4993 Q (
5094 cls .query_type ,
5195 path = path ,
52- ** field_kwargs
96+ query = six . moves . reduce ( operator . or_ , queries )
5397 )
5498 )
5599 else :
56- for field in view .search_nested_fields :
57- # Initial kwargs for the nested query
58- field_kwargs = {field : {'query' : search_term }}
59-
60- # In case if we deal with structure 2
61-
62- extra_field_kwargs = view .search_nested_fields [field ]
63- if extra_field_kwargs :
64- field_kwargs [field ].update (extra_field_kwargs )
65- path = extra_field_kwargs .pop ('path' )
100+ for label , options in view .search_nested_fields .items ():
101+ queries = []
102+ path = options .get ('path' )
103+
104+ for _field in options .get ('fields' , []):
105+ # In case if we deal with structure 2
106+ if isinstance (_field , dict ):
107+ # TODO: take options (ex: boost) into consideration
108+ field = "{}.{}" .format (path , _field ['name' ])
109+ # In case if we deal with structure 1
110+ else :
111+ field = "{}.{}" .format (path , _field )
112+
113+ field_kwargs = {
114+ field : search_term
115+ }
116+
117+ queries .append (
118+ Q ("match" , ** field_kwargs )
119+ )
66120
67- # The match query
68121 __queries .append (
69122 Q (
70123 cls .query_type ,
71124 path = path ,
72- ** field_kwargs
125+ query = six . moves . reduce ( operator . or_ , queries )
73126 )
74127 )
128+
75129 return __queries
76130
77131 @classmethod
0 commit comments