diff --git a/wagtail/wagtailsearch/backends/elasticsearch5.py b/wagtail/wagtailsearch/backends/elasticsearch5.py index 92e7be535..e3987124c 100644 --- a/wagtail/wagtailsearch/backends/elasticsearch5.py +++ b/wagtail/wagtailsearch/backends/elasticsearch5.py @@ -18,6 +18,27 @@ class Elasticsearch5Index(Elasticsearch2Index): class Elasticsearch5SearchQuery(Elasticsearch2SearchQuery): mapping_class = Elasticsearch5Mapping + def _process_lookup(self, field, lookup, value): + column_name = self.mapping.get_field_column_name(field) + + if lookup == 'isnull': + query = { + 'exists': { + 'field': column_name, + } + } + + if value: + query = { + 'bool': { + 'mustNot': query + } + } + + return query + + return super(Elasticsearch5SearchQuery, self)._process_lookup(field, lookup, value) + def _connect_filters(self, filters, connector, negated): if filters: if len(filters) == 1: diff --git a/wagtail/wagtailsearch/tests/test_elasticsearch5_backend.py b/wagtail/wagtailsearch/tests/test_elasticsearch5_backend.py index 0e049b29d..bed0f88e3 100644 --- a/wagtail/wagtailsearch/tests/test_elasticsearch5_backend.py +++ b/wagtail/wagtailsearch/tests/test_elasticsearch5_backend.py @@ -410,7 +410,7 @@ class TestElasticsearch5SearchQuery(TestCase): # Check it expected_result = {'bool': {'filter': [ {'match': {'content_type': 'searchtests.SearchTest'}}, - {'missing': {'field': 'title_filter'}} + {'bool': {'mustNot': {'exists': {'field': 'title_filter'}}}} ], 'must': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.get_query(), expected_result) @@ -421,7 +421,7 @@ class TestElasticsearch5SearchQuery(TestCase): # Check it expected_result = {'bool': {'filter': [ {'match': {'content_type': 'searchtests.SearchTest'}}, - {'missing': {'field': 'title_filter'}} + {'bool': {'mustNot': {'exists': {'field': 'title_filter'}}}} ], 'must': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}} self.assertDictEqual(query.get_query(), expected_result)