Rewrite PlainText to no longer be a shortcut

This commit is contained in:
Karl Hobley 2018-06-08 14:50:03 +01:00
parent 70cee5e195
commit 05dcb32303
3 changed files with 40 additions and 27 deletions

View file

@ -11,7 +11,7 @@ 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, MatchAll, Not, Or, Prefix, SearchQueryShortcut, Term
from wagtail.search.query import And, MatchAll, Not, Or, PlainText, Prefix, SearchQueryShortcut, Term
from wagtail.search.utils import ADD, AND, OR
from .models import SearchAutocomplete as PostgresSearchAutocomplete
@ -235,6 +235,16 @@ class PostgresSearchQueryCompiler(BaseSearchQueryCompiler):
if query is None:
query = self.query
if isinstance(query, PlainText):
operator_class = {
'and': And,
'or': Or,
}[query.operator]
q = operator_class([
Term(term, boost=query.boost)
for term in query.query_string.split()
])
return self.build_database_query(q, config)
if isinstance(query, SearchQueryShortcut):
return self.build_database_query(query.get_equivalent(), config)
if isinstance(query, Prefix):

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, MatchAll, Not, Or, Prefix, SearchQueryShortcut, Term
from wagtail.search.query import And, MatchAll, Not, Or, PlainText, Prefix, SearchQueryShortcut, Term
from wagtail.search.utils import AND, OR
@ -59,6 +59,17 @@ class DatabaseSearchQueryCompiler(BaseSearchQueryCompiler):
if query is None:
query = self.query
if isinstance(query, PlainText):
operator_class = {
'and': And,
'or': Or,
}[query.operator]
q = operator_class([
Term(term, boost=query.boost)
for term in query.query_string.split()
])
return self.build_database_filter(q)
if isinstance(self.query, MatchAll):
return models.Q()

View file

@ -90,6 +90,23 @@ class Not(SearchQueryOperator):
#
class PlainText(SearchQuery):
OPERATORS = ['and', 'or']
DEFAULT_OPERATOR = 'and'
def __init__(self, query_string: str, operator: str = DEFAULT_OPERATOR,
boost: float = 1):
self.query_string = query_string
self.operator = operator.lower()
if self.operator not in self.OPERATORS:
raise ValueError("`operator` must be either 'or' or 'and'.")
self.boost = boost
def apply(self, func):
return func(self.__class__(self.query_string, self.operator,
self.boost))
class MatchAll(SearchQuery):
def apply(self, func):
return self.__class__()
@ -128,31 +145,6 @@ class Fuzzy(SearchQuery):
#
class PlainText(SearchQueryShortcut):
OPERATORS = {
'and': And,
'or': Or,
}
DEFAULT_OPERATOR = 'and'
def __init__(self, query_string: str, operator: str = DEFAULT_OPERATOR,
boost: float = 1):
self.query_string = query_string
self.operator = operator.lower()
if self.operator not in self.OPERATORS:
raise ValueError("`operator` must be either 'or' or 'and'.")
self.boost = boost
def apply(self, func):
return func(self.__class__(self.query_string, self.operator,
self.boost))
def get_equivalent(self):
return self.OPERATORS[self.operator]([
Term(term, boost=self.boost)
for term in self.query_string.split()])
class Boost(SearchQueryShortcut):
def __init__(self, subquery: SearchQuery, boost: float):
self.subquery = subquery