Skip to content

Commit a14aa7d

Browse files
author
Sean Sullivan
committed
Add test for current filter types and refactor filter creation
1 parent 8933791 commit a14aa7d

File tree

2 files changed

+109
-67
lines changed

2 files changed

+109
-67
lines changed

elastic_datashader/elastic.py

Lines changed: 13 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -309,78 +309,25 @@ def build_dsl_filter(filter_inputs) -> Optional[Dict[str, Any]]:
309309
f.get("geo_shape") or
310310
f.get("geo_distance")
311311
)
312-
313-
# Handle spatial filters
314-
if is_spatial_filter:
315-
if f.get("geo_polygon"):
316-
geo_polygon_dict = {"geo_polygon": f.get("geo_polygon")}
317-
if f.get("meta").get("negate"):
318-
filter_dict["must_not"].append(geo_polygon_dict)
319-
else:
320-
filter_dict["filter"].append(geo_polygon_dict)
321-
elif f.get("geo_bounding_box"):
322-
geo_bbox_dict = {"geo_bounding_box": f.get("geo_bounding_box")}
323-
if f.get("meta").get("negate"):
324-
filter_dict["must_not"].append(geo_bbox_dict)
325-
else:
326-
filter_dict["filter"].append(geo_bbox_dict)
327-
elif f.get("geo_shape"):
328-
geo_bbox_dict = {"geo_shape": f.get("geo_shape")}
329-
if f.get("meta").get("negate"):
330-
filter_dict["must_not"].append(geo_bbox_dict)
331-
else:
332-
filter_dict["filter"].append(geo_bbox_dict)
333-
elif f.get("geo_distance"):
334-
geo_bbox_dict = {"geo_distance": f.get("geo_distance")}
335-
if f.get("meta").get("negate"):
336-
filter_dict["must_not"].append(geo_bbox_dict)
337-
else:
338-
filter_dict["filter"].append(geo_bbox_dict)
339-
elif f.get("query"):
340-
if f.get("meta").get("negate"):
341-
filter_dict["must_not"].append(f.get("query"))
342-
else:
343-
filter_dict["filter"].append(f.get("query"))
344-
else:
345-
raise ValueError("unsupported spatial_filter {}".format(f)) # pylint: disable=C0209
346-
347-
# Handle phrase matching
348-
elif f.get("meta").get("type") in ("phrase", "phrases", "bool"):
312+
if f.get("query",None):
349313
if f.get("meta").get("negate"):
350314
filter_dict["must_not"].append(f.get("query"))
351315
else:
352316
filter_dict["filter"].append(f.get("query"))
353-
354-
elif f.get("meta").get("type") in ("range", "exists"):
355-
if f.get("meta").get("negate"):
356-
filter_dict["must_not"].append(handle_range_or_exists_filters(f))
357-
else:
358-
filter_dict["filter"].append(handle_range_or_exists_filters(f))
359-
360-
elif f.get("meta", {}).get("type") == "custom" and f.get("meta", {}).get("key") is not None:
361-
filter_key = f.get("meta", {}).get("key")
362-
if f.get("meta", {}).get("negate"):
363-
if filter_key == "query":
364-
filt_index = list(f.get(filter_key))[0]
365-
filter_dict["must_not"].append({filt_index: f.get(filter_key).get(filt_index)})
366-
else:
367-
filter_dict["must_not"].append({filter_key: f.get(filter_key)})
368-
else:
369-
if filter_key == "query":
370-
filt_index = list(f.get(filter_key))[0]
371-
filter_dict["must_not"].append({filt_index: f.get(filter_key).get(filt_index)})
372-
else:
373-
filter_dict["filter"].append({filter_key: f.get(filter_key)})
374-
375317
else:
376-
# Here we handle filters that don't send a type (this happens when controls send filters)
377-
# example filters[{"meta":{"index":"11503c28-7d88-4f9a-946b-2997a5ea64cf","key":"name"},"query":{"match_phrase":{"name":"word_5"}}}]
378-
if f.get("meta", {}).get("negate"):
379-
filter_dict["must_not"].append(f.get("query"))
318+
if not is_spatial_filter:
319+
filt_type = f.get("meta").get("type")
320+
if f.get("meta").get("negate"):
321+
filter_dict["must_not"].append({filt_type:f.get(filt_type)})
322+
else:
323+
filter_dict["filter"].append({filt_type:f.get(filt_type)})
380324
else:
381-
filter_dict["filter"].append(f.get("query"))
382-
# raise ValueError("unsupported filter type {}".format(f.get("meta").get("type"))) # pylint: disable=C0209
383-
325+
for geo_type in ["geo_polygon","geo_bounding_box","geo_shape","geo_distance"]:
326+
if f.get(geo_type,None):
327+
if f.get("meta").get("negate"):
328+
filter_dict["must_not"].append({geo_type:f.get(geo_type)})
329+
else:
330+
filter_dict["filter"].append({geo_type:f.get(geo_type)})
384331
logger.info("Filter output %s", filter_dict)
385332
return filter_dict
386333

tests/test_elastic.py

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,102 @@ def test_get_search_base():
3333
assert range_filter[params["timestamp_field"]]["lte"] == params["stop_time"]
3434

3535
def test_build_dsl_filter():
36-
pass
36+
meta = {"disabled":False,"negate":False,"alias":None}
37+
# geo_distance with query key (built when you create a filter from the map)
38+
geo_distance = {"geo_distance":{"distance":"260km","point":[-83.89,34.7]}}
39+
q = {"bool":{"must":[{"exists":{"field":"point"}},{**geo_distance}]}}
40+
filters = [{"meta":{**meta,"type":"spatial_filter"},"query":{**q}}]
41+
expected = {'filter': [{'match_all': {}}, {**q}], 'must_not': []}
42+
assert elastic.build_dsl_filter(filters) == expected
43+
44+
# geo_distance filters without query
45+
filters = [{"meta":{**meta},**geo_distance}]
46+
expected = {'filter': [{'match_all': {}}, {**geo_distance}], 'must_not': []}
47+
assert elastic.build_dsl_filter(filters) == expected
48+
49+
# ensure disabled doesn't return a filter
50+
filters[0]['meta']['disabled'] = True
51+
expected = {'filter': [{'match_all': {}}], 'must_not': []}
52+
assert elastic.build_dsl_filter(filters) == expected
53+
54+
# type phrase
55+
phrase = {"match_phrase":{"age":"10"}}
56+
filters = [{"meta":{**meta,"type":"phrase"},"query":{**phrase}}]
57+
expected = {'filter': [{'match_all': {}}, {**phrase}], 'must_not': []}
58+
assert elastic.build_dsl_filter(filters) == expected
59+
60+
# negate phrase
61+
filters[0]['meta']['negate'] = True
62+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**phrase}]}
63+
assert elastic.build_dsl_filter(filters) == expected
64+
65+
# phrases
66+
q = {"bool":{"minimum_should_match":1,"should":[{**phrase},{"match_phrase":{"age":"11"}}]}}
67+
filters = [{"meta":{**meta,"type":"phrases"},"query":{**q}}]
68+
expected = {'filter': [{'match_all': {}}, {**q}], 'must_not': []}
69+
assert elastic.build_dsl_filter(filters) == expected
70+
71+
# negate phrases
72+
filters[0]['meta']['negate'] = True
73+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**q}]}
74+
assert elastic.build_dsl_filter(filters) == expected
75+
76+
# Range filter
77+
rangeFilter = {"range":{"age":{"gte":"2","lt":"10"}}}
78+
filters = [{"meta":{**meta,"type":"range"},**rangeFilter}]
79+
expected = {'filter': [{'match_all': {}},{**rangeFilter}], 'must_not': []}
80+
assert elastic.build_dsl_filter(filters) == expected
81+
82+
# negate Range filter
83+
filters[0]['meta']['negate'] = True
84+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**rangeFilter}]}
85+
assert elastic.build_dsl_filter(filters) == expected
86+
87+
# Range filter using query
88+
filters = [{"meta":{**meta,"type":"range"},"query":{**rangeFilter}}]
89+
expected = {'filter': [{'match_all': {}},{**rangeFilter}], 'must_not': []}
90+
assert elastic.build_dsl_filter(filters) == expected
91+
92+
# negate Range filter
93+
filters[0]['meta']['negate'] = True
94+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**rangeFilter}]}
95+
assert elastic.build_dsl_filter(filters) == expected
96+
97+
# exists
98+
exists = {"exists":{"field": 'age'}}
99+
filters = [{"meta":{**meta,"type":"exists"},**exists}]
100+
expected = {'filter': [{'match_all': {}},{**exists}], 'must_not': []}
101+
assert elastic.build_dsl_filter(filters) == expected
102+
103+
# negate exists
104+
filters[0]['meta']['negate'] = True
105+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**exists}]}
106+
107+
#exists using query
108+
filters = [{"meta":{**meta,"type":"exists"},"query":{**exists}}]
109+
expected = {'filter': [{'match_all': {}},{**exists}], 'must_not': []}
110+
assert elastic.build_dsl_filter(filters) == expected
111+
112+
# negate exists
113+
filters[0]['meta']['negate'] = True
114+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**exists}]}
115+
assert elastic.build_dsl_filter(filters) == expected
116+
117+
# type custom spatial filter using key "query"
118+
q = {"bool":{"must":[{"exists":{"field":"point"}},{**geo_distance}]}}
119+
filters = [{"meta":{**meta,"type":"custom","key":"query"},"query":{**q}}]
120+
expected = {'filter': [{'match_all': {}}, {**q}], 'must_not': []}
121+
assert elastic.build_dsl_filter(filters) == expected
122+
123+
# negate custom filter with key query
124+
filters[0]['meta']['negate'] = True
125+
expected = {'filter': [{'match_all': {}}], 'must_not': [{**q}]}
126+
assert elastic.build_dsl_filter(filters) == expected
127+
128+
# filters from control dont send a type
129+
filters = [{"meta":{**meta},"query":{**phrase}}]
130+
expected = {'filter': [{'match_all': {}},{**phrase}], 'must_not': []}
131+
assert elastic.build_dsl_filter(filters) == expected
37132

38133

39134
def test_get_es_headers():

0 commit comments

Comments
 (0)