Skip to content

Commit 3bf9d79

Browse files
committed
feat: add search operator and fields arguments
allow for more specific search queries by specifying the search_operator and search_fields.
1 parent f0b73e5 commit 3bf9d79

File tree

2 files changed

+69
-5
lines changed

2 files changed

+69
-5
lines changed

grapple/types/structures.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class QuerySetList(graphene.List):
3030
* ``limit``
3131
* ``offset``
3232
* ``search_query``
33+
* ``search_operator``
34+
* ``search_fields``
3335
* ``order``
3436
3537
:param enable_limit: Enable limit argument.
@@ -91,6 +93,19 @@ def __init__(self, of_type, *args, **kwargs):
9193
graphene.String,
9294
description=_("Filter the results using Wagtail's search."),
9395
)
96+
kwargs["search_operator"] = graphene.Argument(
97+
graphene.Enum("SearchOperatorEnum", ["and", "or"]),
98+
description=_(
99+
"Specify search operator (and/or), see: https://docs.wagtail.org/en/stable/topics/search/searching.html#search-operator"
100+
),
101+
default_value="and",
102+
)
103+
kwargs["search_field"] = graphene.Argument(
104+
graphene.List(graphene.String),
105+
description=_(
106+
"A list of fields to search in. see: https://docs.wagtail.org/en/stable/topics/search/searching.html#specifying-the-fields-to-search"
107+
),
108+
)
94109

95110
if "id" not in kwargs:
96111
kwargs["id"] = graphene.Argument(graphene.ID, description=_("Filter by ID"))
@@ -198,6 +213,19 @@ def PaginatedQuerySet(of_type, type_class, **kwargs):
198213
kwargs["search_query"] = graphene.Argument(
199214
graphene.String, description=_("Filter the results using Wagtail's search.")
200215
)
216+
kwargs["search_operator"] = graphene.Argument(
217+
graphene.Enum("SearchOperatorEnum", ["and", "or"]),
218+
description=_(
219+
"Specify search operator (and/or), see: https://docs.wagtail.org/en/stable/topics/search/searching.html#search-operator"
220+
),
221+
default_value="and",
222+
)
223+
kwargs["search_field"] = graphene.Argument(
224+
graphene.List(graphene.String),
225+
description=_(
226+
"A list of fields to search in. see: https://docs.wagtail.org/en/stable/topics/search/searching.html#specifying-the-fields-to-search"
227+
),
228+
)
201229

202230
if "id" not in kwargs:
203231
kwargs["id"] = graphene.Argument(graphene.ID, description=_("Filter by ID"))

grapple/utils.py

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from wagtail.models import Site
55
from wagtail.search.index import class_is_indexed
66
from wagtail.search.models import Query
7+
from wagtail.search.utils import parse_query_string
78

89
from .settings import grapple_settings
910
from .types.structures import BasePaginatedType, PaginationType
@@ -62,6 +63,8 @@ def resolve_queryset(
6263
id=None,
6364
order=None,
6465
collection=None,
66+
search_operator="and",
67+
search_fields=None,
6568
**kwargs,
6669
):
6770
"""
@@ -83,6 +86,11 @@ def resolve_queryset(
8386
:type order: str
8487
:param collection: Use Wagtail's collection id to filter images or documents
8588
:type collection: int
89+
:param search_operator: The operator to use when combining search terms.
90+
Defaults to "and".
91+
:type search_operator: "and" | "or"
92+
:param search_fields: A list of fields to search. Defaults to all fields.
93+
:type search_fields: list
8694
"""
8795

8896
if id is not None:
@@ -112,7 +120,14 @@ def resolve_queryset(
112120
query = Query.get(search_query)
113121
query.add_hit()
114122

115-
qs = qs.search(search_query, order_by_relevance=order_by_relevance)
123+
filters, parsed_query = parse_query_string(search_query, search_operator)
124+
125+
qs = qs.search(
126+
parsed_query,
127+
order_by_relevance=order_by_relevance,
128+
operator=search_operator,
129+
fields=search_fields,
130+
)
116131
if connection.vendor != "sqlite":
117132
qs = qs.annotate_score("search_score")
118133

@@ -153,7 +168,16 @@ def get_paginated_result(qs, page, per_page):
153168

154169

155170
def resolve_paginated_queryset(
156-
qs, info, page=None, per_page=None, search_query=None, id=None, order=None, **kwargs
171+
qs,
172+
info,
173+
page=None,
174+
per_page=None,
175+
id=None,
176+
order=None,
177+
search_query=None,
178+
search_operator="and",
179+
search_fields=None,
180+
**kwargs,
157181
):
158182
"""
159183
Add page, per_page and search capabilities to the query. This contains
@@ -167,11 +191,16 @@ def resolve_paginated_queryset(
167191
:type id: int
168192
:param per_page: The maximum number of items to include on a page.
169193
:type per_page: int
194+
:param order: Order the query set using the Django QuerySet order_by format.
195+
:type order: str
170196
:param search_query: Using Wagtail search, exclude objects that do not match
171197
the search query.
172198
:type search_query: str
173-
:param order: Order the query set using the Django QuerySet order_by format.
174-
:type order: str
199+
:param search_operator: The operator to use when combining search terms.
200+
Defaults to "and".
201+
:type search_operator: "and" | "or"
202+
:param search_fields: A list of fields to search. Defaults to all fields.
203+
:type search_fields: list
175204
"""
176205
page = int(page or 1)
177206
per_page = min(
@@ -199,7 +228,14 @@ def resolve_paginated_queryset(
199228
query = Query.get(search_query)
200229
query.add_hit()
201230

202-
qs = qs.search(search_query, order_by_relevance=order_by_relevance)
231+
filters, parsed_query = parse_query_string(search_query, search_operator)
232+
233+
qs = qs.search(
234+
parsed_query,
235+
order_by_relevance=order_by_relevance,
236+
operator=search_operator,
237+
fields=search_fields,
238+
)
203239
if connection.vendor != "sqlite":
204240
qs = qs.annotate_score("search_score")
205241

0 commit comments

Comments
 (0)