Remove term level query classes

This commit is contained in:
Karl Hobley 2018-06-08 15:35:19 +01:00
parent 0fbac14d3c
commit 40c44d6d18
5 changed files with 30 additions and 118 deletions

View file

@ -11,10 +11,9 @@ from django.utils.encoding import force_text
from wagtail.search.backends.base import (
BaseSearchBackend, BaseSearchQueryCompiler, BaseSearchResults)
from wagtail.search.index import RelatedFields, SearchField, get_indexed_models
from wagtail.search.query import And, Boost, MatchAll, Not, Or, PlainText, Prefix, Term
from wagtail.search.query import And, Boost, MatchAll, Not, Or, PlainText
from wagtail.search.utils import ADD, AND, OR
from .models import SearchAutocomplete as PostgresSearchAutocomplete
from .models import IndexEntry
from .utils import (
get_content_type_pk, get_descendants_content_types_pks, get_postgresql_connections,
@ -236,26 +235,20 @@ class PostgresSearchQueryCompiler(BaseSearchQueryCompiler):
query = self.query
if isinstance(query, PlainText):
operator_class = {
'and': And,
'or': Or,
self.check_boost(query, boost=boost)
operator = {
'and': AND,
'or': OR,
}[query.operator]
q = operator_class([
Term(term, boost=query.boost)
return operator([
PostgresSearchQuery(unidecode(term), config=config)
for term in query.query_string.split()
])
return self.build_database_query(q, config, boost=boost)
if isinstance(query, Boost):
boost *= query.boost
return self.build_database_query(query.subquery, config, boost=boost)
if isinstance(query, Prefix):
self.check_boost(query, boost=boost)
self.is_autocomplete = True
return PostgresSearchAutocomplete(unidecode(query.prefix),
config=config)
if isinstance(query, Term):
self.check_boost(query, boost=boost)
return PostgresSearchQuery(unidecode(query.term), config=config)
if isinstance(query, Not):
return ~self.build_database_query(query.subquery, config, boost=boost)
if isinstance(query, And):

View file

@ -5,7 +5,7 @@ from django.db.models.expressions import Value
from wagtail.search.backends.base import (
BaseSearchBackend, BaseSearchQueryCompiler, BaseSearchResults)
from wagtail.search.query import And, Boost, MatchAll, Not, Or, PlainText, Prefix, Term
from wagtail.search.query import And, Boost, MatchAll, Not, Or, PlainText
from wagtail.search.utils import AND, OR
@ -60,15 +60,17 @@ class DatabaseSearchQueryCompiler(BaseSearchQueryCompiler):
query = self.query
if isinstance(query, PlainText):
operator_class = {
'and': And,
'or': Or,
self.check_boost(query, boost=boost)
operator = {
'and': AND,
'or': OR,
}[query.operator]
q = operator_class([
Term(term, boost=query.boost)
return operator([
self.build_single_term_filter(term)
for term in query.query_string.split()
])
return self.build_database_filter(q, boost=boost)
if isinstance(query, Boost):
boost *= query.boost
@ -77,12 +79,6 @@ class DatabaseSearchQueryCompiler(BaseSearchQueryCompiler):
if isinstance(self.query, MatchAll):
return models.Q()
if isinstance(query, Term):
self.check_boost(query)
return self.build_single_term_filter(query.term)
if isinstance(query, Prefix):
self.check_boost(query)
return self.build_single_term_filter(query.prefix)
if isinstance(query, Not):
return ~self.build_database_filter(query.subquery, boost=boost)
if isinstance(query, And):

View file

@ -13,8 +13,7 @@ from elasticsearch.helpers import bulk
from wagtail.search.backends.base import (
BaseSearchBackend, BaseSearchQueryCompiler, BaseSearchResults)
from wagtail.search.index import FilterField, Indexed, RelatedFields, SearchField, class_is_indexed
from wagtail.search.query import (
And, Boost, Fuzzy, MatchAll, Not, Or, PlainText, Prefix, Term)
from wagtail.search.query import And, Boost, MatchAll, Not, Or, PlainText
from wagtail.utils.deprecation import RemovedInWagtail22Warning
from wagtail.utils.utils import deep_update
@ -380,20 +379,6 @@ class Elasticsearch2SearchQueryCompiler(BaseSearchQueryCompiler):
return filter_out
def _compile_term_query(self, query_type, value, field, boost=1.0, **extra):
term_query = {
'value': value,
}
if boost != 1.0:
term_query['boost'] = boost
return {
query_type: {
field: term_query,
}
}
def _compile_plaintext_query(self, query, fields, boost=1.0):
match_query = {
'query': query.query_string
@ -427,15 +412,6 @@ class Elasticsearch2SearchQueryCompiler(BaseSearchQueryCompiler):
return {'match_all': match_all_query}
elif isinstance(query, Term):
return self._compile_term_query('term', query.term, field, query.boost * boost)
elif isinstance(query, Prefix):
return self._compile_term_query('prefix', query.prefix, field, query.boost * boost)
elif isinstance(query, Fuzzy):
return self._compile_term_query('fuzzy', query.term, field, query.boost * boost, fuzziness=query.max_distance)
elif isinstance(query, And):
return {
'bool': {

View file

@ -114,32 +114,4 @@ class Boost(SearchQuery):
return func(self.__class__(self.subquery.apply(func), self.boost))
class Term(SearchQuery):
def __init__(self, term: str, boost: float = 1):
self.term = term
self.boost = boost
def apply(self, func):
return func(self.__class__(self.term, self.boost))
class Prefix(SearchQuery):
def __init__(self, prefix: str, boost: float = 1):
self.prefix = prefix
self.boost = boost
def apply(self, func):
return func(self.__class__(self.prefix, self.boost))
class Fuzzy(SearchQuery):
def __init__(self, term: str, max_distance: float = 3, boost: float = 1):
self.term = term
self.max_distance = max_distance
self.boost = boost
def apply(self, func):
return func(self.__class__(self.term, self.max_distance, self.boost))
MATCH_ALL = MatchAll()

View file

@ -13,7 +13,7 @@ from wagtail.search.backends import (
InvalidSearchBackendError, get_search_backend, get_search_backends)
from wagtail.search.backends.base import FieldError
from wagtail.search.backends.db import DatabaseSearchBackend
from wagtail.search.query import MATCH_ALL, And, Boost, Not, Or, PlainText, Prefix, Term
from wagtail.search.query import MATCH_ALL, And, Boost, Not, Or, PlainText
from wagtail.tests.search import models
from wagtail.tests.utils import WagtailTestUtils
@ -452,39 +452,25 @@ class BackendTests(WagtailTestUtils):
results = self.backend.search(MATCH_ALL, models.Book.objects.all())
self.assertEqual(len(results), 13)
def test_term(self):
results = self.backend.search(Term('javascript'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'JavaScript: The Definitive Guide',
'JavaScript: The good parts'})
def test_incomplete_term(self):
results = self.backend.search(Term('pro'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results}, set())
def test_and(self):
results = self.backend.search(And([Term('javascript'),
Term('definitive')]),
results = self.backend.search(And([PlainText('javascript'),
PlainText('definitive')]),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'JavaScript: The Definitive Guide'})
results = self.backend.search(Term('javascript') & Term('definitive'),
results = self.backend.search(PlainText('javascript') & PlainText('definitive'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'JavaScript: The Definitive Guide'})
def test_or(self):
results = self.backend.search(Or([Term('hobbit'), Term('towers')]),
results = self.backend.search(Or([PlainText('hobbit'), PlainText('towers')]),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'The Hobbit', 'The Two Towers'})
results = self.backend.search(Term('hobbit') | Term('towers'),
results = self.backend.search(PlainText('hobbit') | PlainText('towers'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'The Hobbit', 'The Two Towers'})
@ -504,19 +490,19 @@ class BackendTests(WagtailTestUtils):
'Two Scoops of Django 1.11',
}
results = self.backend.search(Not(Term('javascript')),
results = self.backend.search(Not(PlainText('javascript')),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results}, all_other_titles)
results = self.backend.search(~Term('javascript'),
results = self.backend.search(~PlainText('javascript'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results}, all_other_titles)
def test_operators_combination(self):
results = self.backend.search(
((Term('javascript') & ~Term('definitive')) |
Term('python') | Term('rust')) |
Term('two'),
((PlainText('javascript') & ~PlainText('definitive')) |
PlainText('python') | PlainText('rust')) |
PlainText('two'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'JavaScript: The good parts',
@ -525,17 +511,6 @@ class BackendTests(WagtailTestUtils):
'The Rust Programming Language',
'Two Scoops of Django 1.11'})
def test_prefix_single_word(self):
results = self.backend.search(Prefix('pro'), models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'The Rust Programming Language'})
def test_prefix_multiple_words(self):
results = self.backend.search(Prefix('rust pro'),
models.Book.objects.all())
self.assertSetEqual({r.title for r in results},
{'The Rust Programming Language'})
#
# Shortcut query classes
#