From 781263d4e1d4d8c95170f19667b61700fd3751d9 Mon Sep 17 00:00:00 2001 From: Bertrand Bordage Date: Thu, 19 Oct 2017 11:44:43 +0100 Subject: [PATCH] Optimizes the PostgreSQL search query generated by the ORM. Makes queries at least as fast as before. --- wagtail/contrib/postgres_search/backend.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/wagtail/contrib/postgres_search/backend.py b/wagtail/contrib/postgres_search/backend.py index 2b17ec77b9..9fa8655fa0 100644 --- a/wagtail/contrib/postgres_search/backend.py +++ b/wagtail/contrib/postgres_search/backend.py @@ -198,20 +198,26 @@ class PostgresSearchQuery(BaseSearchQuery): if self.query_string is None: return self.queryset[start:stop] search_query = self.get_search_query(config=config) + queryset = self.queryset + query = queryset.query if self.fields is None: - search_annotation = F('index_entries__body_search') + vector = F('index_entries__body_search') else: - search_annotation = ADD( + vector = ADD( SearchVector(field, config=search_query.config, weight=get_weight(self.get_boost(field))) for field in self.fields) - queryset = (self.queryset.annotate(_search_=search_annotation) - .filter(_search_=search_query)) + vector = vector.resolve_expression(query) + search_query = search_query.resolve_expression(query) + lookup = IndexEntry._meta.get_field('body_search').get_lookup('exact')( + vector, search_query) + query.where.add(lookup, 'AND') if self.order_by_relevance: - queryset = queryset.annotate( - _rank_=SearchRank(F('_search_'), search_query, - weights=WEIGHTS_VALUES) - ).order_by('-_rank_', '-pk') + # Due to a Django bug, arrays are not automatically converted here. + converted_weights = '{' + ','.join(map(str, WEIGHTS_VALUES)) + '}' + queryset = queryset.order_by(SearchRank(vector, search_query, + weights=converted_weights).desc(), + '-pk') elif not queryset.query.order_by: # Adds a default ordering to avoid issue #3729. queryset = queryset.order_by('-pk')