From 05dcb32303250e02235cc7df4a164fd5cb2678bc Mon Sep 17 00:00:00 2001 From: Karl Hobley Date: Fri, 8 Jun 2018 14:50:03 +0100 Subject: [PATCH] Rewrite PlainText to no longer be a shortcut --- wagtail/contrib/postgres_search/backend.py | 12 ++++++- wagtail/search/backends/db.py | 13 ++++++- wagtail/search/query.py | 42 +++++++++------------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/wagtail/contrib/postgres_search/backend.py b/wagtail/contrib/postgres_search/backend.py index 5ec932417..1664e5355 100644 --- a/wagtail/contrib/postgres_search/backend.py +++ b/wagtail/contrib/postgres_search/backend.py @@ -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): diff --git a/wagtail/search/backends/db.py b/wagtail/search/backends/db.py index 31ac73f94..3e92c66c6 100644 --- a/wagtail/search/backends/db.py +++ b/wagtail/search/backends/db.py @@ -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() diff --git a/wagtail/search/query.py b/wagtail/search/query.py index a6c53a6b2..ca3557c83 100644 --- a/wagtail/search/query.py +++ b/wagtail/search/query.py @@ -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