0
0
mirror of https://github.com/wagtail/wagtail.git synced 2024-12-01 11:41:20 +01:00

Special case date lookups for searching

This commit is contained in:
seb-b 2021-02-25 21:10:13 +11:00 committed by GitHub
parent aefff4e56c
commit 45de8f0daa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 58 additions and 1 deletions

View File

@ -1,5 +1,7 @@
from warnings import warn
from django.db.models.functions.datetime import Extract as ExtractDate
from django.db.models.functions.datetime import ExtractYear
from django.db.models.lookups import Lookup
from django.db.models.query import QuerySet
from django.db.models.sql.where import SubqueryConstraint, WhereNode
@ -88,7 +90,16 @@ class BaseSearchQueryCompiler:
def _get_filters_from_where_node(self, where_node, check_only=False):
# Check if this is a leaf node
if isinstance(where_node, Lookup):
field_attname = where_node.lhs.target.attname
if isinstance(where_node.lhs, ExtractDate):
if isinstance(where_node.lhs, ExtractYear):
field_attname = where_node.lhs.lhs.target.attname
else:
raise FilterError(
'Cannot apply filter on search results: "' + where_node.lhs.lookup_name
+ '" queries are not supported.'
)
else:
field_attname = where_node.lhs.target.attname
lookup = where_node.lookup_name
value = where_node.rhs

View File

@ -176,6 +176,19 @@ class ElasticsearchCommonSearchBackendTests(BackendTests):
results = self.backend.search(MATCH_ALL, models.Book)[110:]
self.assertEqual(len(results), 54)
def test_search_with_date_filter(self):
after_1900 = models.Book.objects.filter(publication_date__year__gt=1900)
results = self.backend.search(MATCH_ALL, after_1900)
self.assertEqual(len(after_1900), len(results))
# Filtering by date not supported, should throw a FilterError
from wagtail.search.backends.base import FilterError
in_jan = models.Book.objects.filter(publication_date__month=1)
with self.assertRaises(FilterError):
self.backend.search(MATCH_ALL, in_jan)
# Elasticsearch always does prefix matching on `partial_match` fields,
# even when we dont use `Prefix`.
@unittest.expectedFailure

View File

@ -333,6 +333,17 @@ class TestElasticsearch5SearchQuery(TestCase):
expected_result = {'match_phrase': {'title': "Hello world"}}
self.assertDictEqual(query_compiler.get_inner_query(), expected_result)
def test_year_filter(self):
# Create a query
query_compiler = self.query_compiler_class(models.Book.objects.filter(publication_date__year__gt=1900), "Hello")
# Check it
expected_result = {'bool': {'filter': [
{'match': {'content_type': 'searchtests.Book'}},
{'range': {'publication_date_filter': {'gt': 1900}}}
], 'must': {'multi_match': {'query': 'Hello', 'fields': ['_all', '_partials']}}}}
self.assertDictEqual(query_compiler.get_query(), expected_result)
class TestElasticsearch5SearchResults(TestCase):
fixtures = ['search']

View File

@ -333,6 +333,17 @@ class TestElasticsearch6SearchQuery(TestCase):
expected_result = {'match_phrase': {'title': "Hello world"}}
self.assertDictEqual(query_compiler.get_inner_query(), expected_result)
def test_year_filter(self):
# Create a query
query_compiler = self.query_compiler_class(models.Book.objects.filter(publication_date__year=1900), "Hello")
# Check it
expected_result = {'bool': {'filter': [
{'match': {'content_type': 'searchtests.Book'}},
{'term': {'publication_date_filter': 1900}}
], 'must': {'multi_match': {'query': 'Hello', 'fields': ['_all_text', '_edgengrams']}}}}
self.assertDictEqual(query_compiler.get_query(), expected_result)
class TestElasticsearch6SearchResults(TestCase):
fixtures = ['search']

View File

@ -333,6 +333,17 @@ class TestElasticsearch7SearchQuery(TestCase):
expected_result = {'match_phrase': {'title': "Hello world"}}
self.assertDictEqual(query_compiler.get_inner_query(), expected_result)
def test_year_filter(self):
# Create a query
query_compiler = self.query_compiler_class(models.Book.objects.filter(publication_date__year__lt=1900), "Hello")
# Check it
expected_result = {'bool': {'filter': [
{'match': {'content_type': 'searchtests.Book'}},
{'range': {'publication_date_filter': {'lt': 1900}}}
], 'must': {'multi_match': {'query': 'Hello', 'fields': ['_all_text', '_edgengrams']}}}}
self.assertDictEqual(query_compiler.get_query(), expected_result)
class TestElasticsearch7SearchResults(TestCase):
fixtures = ['search']