From 9cc8d68ceeed7fe14bfcd84914f4bd54775036af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Bedna=C5=99=C3=ADk?= <jan.bednarik@gmail.com> Date: Sat, 10 Nov 2018 22:22:35 +0100 Subject: [PATCH] Sort reports --- openlobby/core/api/schema.py | 19 ++++++++-- openlobby/core/models.py | 6 ++++ openlobby/core/search.py | 18 ++++++++-- tests/dummy.py | 2 +- tests/schema/snapshots/snap_test_authors.py | 2 +- .../snapshots/snap_test_search_reports.py | 4 +-- tests/schema/test_search_reports.py | 35 +++++++++++++++++++ tests/test_search.py | 33 +++++++++++++++-- 8 files changed, 108 insertions(+), 11 deletions(-) diff --git a/openlobby/core/api/schema.py b/openlobby/core/api/schema.py index 4864d20..8fa85f8 100644 --- a/openlobby/core/api/schema.py +++ b/openlobby/core/api/schema.py @@ -6,10 +6,11 @@ from .paginator import Paginator from .sanitizers import extract_text from .. import search from ..models import OpenIdClient -from ..models import User, Report, UserSort +from ..models import User, Report, UserSort, ReportSort UserSortEnum = graphene.Enum.from_enum(UserSort) +ReportSortEnum = graphene.Enum.from_enum(ReportSort) class AuthorsConnection(relay.Connection): @@ -50,6 +51,10 @@ class Query: description="Fulltext search in Reports. Returns first 10 nodes if pagination is not specified.", query=graphene.String(description="Text to search for."), highlight=graphene.Boolean(default_value=False, description=highlight_help), + sort=ReportSortEnum(), + reversed=graphene.Boolean( + default_value=False, description="Reverse order of sort." + ), ) viewer = graphene.Field(types.User, description="Active user viewing API.") login_shortcuts = graphene.List( @@ -84,10 +89,20 @@ class Query: def resolve_search_reports(self, info, **kwargs): paginator = Paginator(**kwargs) + query = kwargs.get("query", "") query = extract_text(query) - params = {"highlight": kwargs.get("highlight")} + + params = { + "highlight": kwargs.get("highlight"), + "reversed": kwargs.get("reversed"), + } + + if "sort" in kwargs: + params["sort"] = ReportSort(kwargs["sort"]) + response = search.search_reports(paginator, query=query, **params) + total = response.hits.total page_info = paginator.get_page_info(total) diff --git a/openlobby/core/models.py b/openlobby/core/models.py index a7c9aed..41e365a 100644 --- a/openlobby/core/models.py +++ b/openlobby/core/models.py @@ -15,6 +15,12 @@ class UserSort(Enum): TOTAL_REPORTS = "total_reports" +class ReportSort(Enum): + DATE = "date" + PUBLISHED = "published" + RELEVANCE = "relevance" + + class CustomUserManager(UserManager): def with_total_reports(self): return self.get_queryset().annotate( diff --git a/openlobby/core/search.py b/openlobby/core/search.py index b9b2df0..84fcf16 100644 --- a/openlobby/core/search.py +++ b/openlobby/core/search.py @@ -1,4 +1,5 @@ from .documents import ReportDoc +from .models import ReportSort HIGHLIGHT_PARAMS = { @@ -8,7 +9,15 @@ HIGHLIGHT_PARAMS = { } -def search_reports(paginator, *, query=None, highlight=False, author_id=None): +def search_reports( + paginator, + *, + query=None, + highlight=False, + author_id=None, + sort=ReportSort.PUBLISHED, + reversed=False, +): fields = [ "title", "body", @@ -31,7 +40,12 @@ def search_reports(paginator, *, query=None, highlight=False, author_id=None): if highlight: s = s.highlight(*fields, **HIGHLIGHT_PARAMS) - s = s.sort("-published") + if sort == ReportSort.PUBLISHED: + s = s.sort("published" if reversed else "-published") + elif sort == ReportSort.DATE: + s = s.sort("date" if reversed else "-date") + elif sort == ReportSort.RELEVANCE: + s = s.sort({"_score": {"order": "asc" if reversed else "desc"}}, "-published") s = s[paginator.slice_from : paginator.slice_to] return s.execute() diff --git a/tests/dummy.py b/tests/dummy.py index fc2e23a..27c05e6 100644 --- a/tests/dummy.py +++ b/tests/dummy.py @@ -56,7 +56,7 @@ reports = [ }, { "id": 3, - "date": arrow.get(2018, 1, 5).datetime, + "date": arrow.get(2018, 1, 2).datetime, "published": arrow.get(2018, 1, 6).datetime, "edited": arrow.get(2018, 1, 6, 7).datetime, "title": "The Return of the King", diff --git a/tests/schema/snapshots/snap_test_authors.py b/tests/schema/snapshots/snap_test_authors.py index 83db2ae..a8d2ba1 100644 --- a/tests/schema/snapshots/snap_test_authors.py +++ b/tests/schema/snapshots/snap_test_authors.py @@ -232,7 +232,7 @@ snapshots['test_with_reports 1'] = { 'cursor': 'MQ==', 'node': { 'body': 'Aragorn is the King. And we have lost the Ring.', - 'date': '2018-01-05 00:00:00+00:00', + 'date': '2018-01-02 00:00:00+00:00', 'edited': '2018-01-06 07:00:00+00:00', 'extra': None, 'id': 'UmVwb3J0OjM=', diff --git a/tests/schema/snapshots/snap_test_search_reports.py b/tests/schema/snapshots/snap_test_search_reports.py index 958d01e..8717665 100644 --- a/tests/schema/snapshots/snap_test_search_reports.py +++ b/tests/schema/snapshots/snap_test_search_reports.py @@ -23,7 +23,7 @@ snapshots['test_all 1'] = { 'totalReports': 2 }, 'body': 'Aragorn is the King. And we have lost the Ring.', - 'date': '2018-01-05 00:00:00+00:00', + 'date': '2018-01-02 00:00:00+00:00', 'edited': '2018-01-06 07:00:00+00:00', 'extra': None, 'hasRevisions': False, @@ -153,7 +153,7 @@ snapshots['test_highlight 1'] = { 'totalReports': 2 }, 'body': 'Aragorn is the King. And we have lost the <mark>Ring</mark>.', - 'date': '2018-01-05 00:00:00+00:00', + 'date': '2018-01-02 00:00:00+00:00', 'edited': '2018-01-06 07:00:00+00:00', 'extra': None, 'hasRevisions': False, diff --git a/tests/schema/test_search_reports.py b/tests/schema/test_search_reports.py index e803019..2717c6b 100644 --- a/tests/schema/test_search_reports.py +++ b/tests/schema/test_search_reports.py @@ -1,4 +1,5 @@ import pytest +from graphql_relay import from_global_id from ..dummy import prepare_reports @@ -231,3 +232,37 @@ def test_last_before(call_api, snapshot): """ response = call_api(query) snapshot.assert_match(response) + + +@pytest.mark.parametrize( + "params, expected_ids", + [ + ("sort: PUBLISHED", [3, 2, 1]), + ("sort: PUBLISHED, reversed: true", [1, 2, 3]), + ("sort: DATE", [2, 3, 1]), + ("sort: DATE, reversed: true", [1, 3, 2]), + ("sort: RELEVANCE", [3, 2, 1]), + ("sort: RELEVANCE, reversed: true", [3, 2, 1]), + ('query: "ring", sort: RELEVANCE', [1, 3]), + ('query: "ring", sort: RELEVANCE, reversed: true', [3, 1]), + ], +) +def test_sort(params, expected_ids, call_api, snapshot): + prepare_reports() + query = f""" + query {{ + searchReports ({params}) {{ + totalCount + edges {{ + cursor + node {{ + id + }} + }} + }} + }} + """ + response = call_api(query) + ids = [edge["node"]["id"] for edge in response["data"]["searchReports"]["edges"]] + ids = [int(id) for type, id in map(from_global_id, ids)] + assert ids == expected_ids diff --git a/tests/test_search.py b/tests/test_search.py index aadd37d..c1efcd7 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -1,6 +1,7 @@ import pytest from openlobby.core.api.paginator import Paginator, encode_cursor +from openlobby.core.models import ReportSort from openlobby.core.search import search_reports from .dummy import prepare_reports @@ -13,7 +14,7 @@ pytestmark = [pytest.mark.django_db, pytest.mark.usefixtures("django_es")] "query, expected_ids", [("", [3, 2, 1]), ("sauron", [3, 2]), ("towers", [2]), ("Aragorn Gandalf", [3, 1])], ) -def test_search_reports(query, expected_ids): +def test_search_reports__query(query, expected_ids): prepare_reports() paginator = Paginator() response = search_reports(paginator, query=query) @@ -35,9 +36,8 @@ def test_search_reports__highlight(): ) def test_search_reports__pagination(first, after, expected_ids): prepare_reports() - query = "" paginator = Paginator(first=first, after=after) - response = search_reports(paginator, query=query) + response = search_reports(paginator) assert expected_ids == [int(r.meta.id) for r in response] @@ -58,3 +58,30 @@ def test_search_reports__by_author__pagination(first, after, expected_ids): paginator = Paginator(first=first, after=after) response = search_reports(paginator, author_id=author_id) assert expected_ids == [int(r.meta.id) for r in response] + + +def test_search_reports__sort__default(): + prepare_reports() + paginator = Paginator() + response = search_reports(paginator) + assert [3, 2, 1] == [int(r.meta.id) for r in response] + + +@pytest.mark.parametrize( + "query, sort, reversed, expected_ids", + [ + (None, ReportSort.PUBLISHED, False, [3, 2, 1]), + (None, ReportSort.PUBLISHED, True, [1, 2, 3]), + (None, ReportSort.DATE, False, [2, 3, 1]), + (None, ReportSort.DATE, True, [1, 3, 2]), + (None, ReportSort.RELEVANCE, False, [3, 2, 1]), + (None, ReportSort.RELEVANCE, True, [3, 2, 1]), + ("ring", ReportSort.RELEVANCE, False, [1, 3]), + ("ring", ReportSort.RELEVANCE, True, [3, 1]), + ], +) +def test_search_reports__sort(query, sort, reversed, expected_ids): + prepare_reports() + paginator = Paginator() + response = search_reports(paginator, query=query, sort=sort, reversed=reversed) + assert expected_ids == [int(r.meta.id) for r in response] -- GitLab