diff --git a/document_stores/elasticsearch/src/elasticsearch_haystack/filters.py b/document_stores/elasticsearch/src/elasticsearch_haystack/filters.py index f7d884e2a..66adaacf7 100644 --- a/document_stores/elasticsearch/src/elasticsearch_haystack/filters.py +++ b/document_stores/elasticsearch/src/elasticsearch_haystack/filters.py @@ -81,7 +81,18 @@ def _parse_comparison(field: str, comparison: Union[Dict, List, str, float]) -> raise FilterError(msg) result.append({"range": {field: {comparator[1:]: val}}}) elif comparator in ["$not", "$or"]: - result.append(_normalize_filters(val, comparator)) + if isinstance(val, list): + # This handles corner cases like this: + # `{"name": {"$or": [{"$eq": "name_0"}, {"$eq": "name_1"}]}}` + # If we don't handle it like this we'd lose the "name" field and the + # generated query would be wrong and return unexpected results. + comparisons = [_parse_comparison(field, v)[0] for v in val] + if comparator == "$not": + result.append({"bool": {"must_not": comparisons}}) + elif comparator == "$or": + result.append({"bool": {"should": comparisons}}) + else: + result.append(_normalize_filters(val, comparator)) elif comparator == "$and" and isinstance(val, list): # We're assuming there are no duplicate items in the list flat_filters = {k: v for d in val for k, v in d.items()} diff --git a/document_stores/elasticsearch/tests/test_filters.py b/document_stores/elasticsearch/tests/test_filters.py index 02e823232..efaa168b0 100644 --- a/document_stores/elasticsearch/tests/test_filters.py +++ b/document_stores/elasticsearch/tests/test_filters.py @@ -126,8 +126,8 @@ { "bool": { "should": [ - {"match": {"$eq": {"query": "name_0", "minimum_should_match": "100%"}}}, - {"match": {"$eq": {"query": "name_1", "minimum_should_match": "100%"}}}, + {"term": {"name": "name_0"}}, + {"term": {"name": "name_1"}}, ] } }, @@ -168,6 +168,21 @@ {"number": {"$and": [{"$lte": 2}, {"$gte": 0}]}}, {"bool": {"must": [{"range": {"number": {"lte": 2, "gte": 0}}}]}}, ), + ( + {"name": {"$or": [{"$eq": "name_0"}, {"$eq": "name_1"}]}}, + { + "bool": { + "must": { + "bool": { + "should": [ + {"term": {"name": "name_0"}}, + {"term": {"name": "name_1"}}, + ] + } + } + } + }, + ), ]