From 11244d46e519537e6705800ee0217ce6d274a5ec Mon Sep 17 00:00:00 2001 From: Darrel O'Pry Date: Tue, 17 Jan 2023 16:04:46 -0500 Subject: [PATCH] Fix order_by_relevance needed for Postgres and queryset ordered searches (#299) --- example/example/tests/test_grapple.py | 21 ++++++++++++--------- grapple/utils.py | 19 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/example/example/tests/test_grapple.py b/example/example/tests/test_grapple.py index 9f23060e..54ef5f55 100644 --- a/example/example/tests/test_grapple.py +++ b/example/example/tests/test_grapple.py @@ -440,17 +440,17 @@ class PagesSearchTest(BaseGrappleTest): def setUpTestData(cls): cls.home = HomePage.objects.first() BlogPageFactory(title="Alpha", parent=cls.home) - BlogPageFactory(title="Alpha Alpha", parent=cls.home) + BlogPageFactory(title="Gamma Beta", parent=cls.home) BlogPageFactory(title="Alpha Beta", parent=cls.home) + BlogPageFactory(title="Beta Alpha", parent=cls.home) BlogPageFactory(title="Alpha Gamma", parent=cls.home) BlogPageFactory(title="Beta", parent=cls.home) - BlogPageFactory(title="Beta Alpha", parent=cls.home) + BlogPageFactory(title="Alpha Alpha", parent=cls.home) + BlogPageFactory(title="Gamma Gamma", parent=cls.home) BlogPageFactory(title="Beta Beta", parent=cls.home) - BlogPageFactory(title="Beta Gamma", parent=cls.home) BlogPageFactory(title="Gamma", parent=cls.home) + BlogPageFactory(title="Beta Gamma", parent=cls.home) BlogPageFactory(title="Gamma Alpha", parent=cls.home) - BlogPageFactory(title="Gamma Beta", parent=cls.home) - BlogPageFactory(title="Gamma Gamma", parent=cls.home) def test_natural_order(self): query = """ @@ -460,15 +460,18 @@ def test_natural_order(self): } } """ + """ + sqlite doesn't support scoring so natural order will be in the order of defintion. + with another database or elasticsearch backend the order will be different + """ executed = self.client.execute(query, variables={"searchQuery": "Alpha"}) page_data = executed["data"].get("pages") - self.assertEquals(len(page_data), 6) self.assertEquals(page_data[0]["title"], "Alpha") - self.assertEquals(page_data[1]["title"], "Alpha Alpha") - self.assertEquals(page_data[2]["title"], "Alpha Beta") + self.assertEquals(page_data[1]["title"], "Alpha Beta") + self.assertEquals(page_data[2]["title"], "Beta Alpha") self.assertEquals(page_data[3]["title"], "Alpha Gamma") - self.assertEquals(page_data[4]["title"], "Beta Alpha") + self.assertEquals(page_data[4]["title"], "Alpha Alpha") self.assertEquals(page_data[5]["title"], "Gamma Alpha") def test_explicit_order(self): diff --git a/grapple/utils.py b/grapple/utils.py index 793999ea..12e517d2 100644 --- a/grapple/utils.py +++ b/grapple/utils.py @@ -3,7 +3,6 @@ from django.conf import settings from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator -from wagtail.search.backends import get_search_backend from wagtail.search.index import class_is_indexed from wagtail.search.models import Query @@ -103,8 +102,10 @@ def resolve_queryset( else: qs = qs.all() + order_by_relevance = True if order is not None: qs = qs.order_by(*(x.strip() for x in order.split(","))) + order_by_relevance = False if collection is not None: try: @@ -123,7 +124,7 @@ def resolve_queryset( query = Query.get(search_query) query.add_hit() - qs = get_search_backend().search(search_query, qs) + qs = qs.search(search_query, order_by_relevance=order_by_relevance) return _sliced_queryset(qs, limit, offset) @@ -192,6 +193,13 @@ def resolve_paginated_queryset( else: qs = qs.all() + # order_by_relevance will always take precedence over an existing order_by in the Postgres backend + # we need to set it to False if we want to specify our own order_by. + order_by_relevance = True + if order is not None: + qs = qs.order_by(*(x.strip() for x in order.split(","))) + order_by_relevance = False + if id is None and search_query: # Check if the queryset is searchable using Wagtail search. if not class_is_indexed(qs.model): @@ -201,12 +209,7 @@ def resolve_paginated_queryset( query = Query.get(search_query) query.add_hit() - results = get_search_backend().search(search_query, qs) - - return get_paginated_result(results, page, per_page) - - if order is not None: - qs = qs.order_by(*(x.strip() for x in order.split(","))) + qs = qs.search(search_query, order_by_relevance=order_by_relevance) return get_paginated_result(qs, page, per_page)