Skip to content

Commit

Permalink
feat: add search operator and fields arguments
Browse files Browse the repository at this point in the history
allow for more specific search queries by specifying the search_operator
and search_fields.
  • Loading branch information
dopry committed May 12, 2023
1 parent f0b73e5 commit 3bf9d79
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 5 deletions.
28 changes: 28 additions & 0 deletions grapple/types/structures.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class QuerySetList(graphene.List):
* ``limit``
* ``offset``
* ``search_query``
* ``search_operator``
* ``search_fields``
* ``order``
:param enable_limit: Enable limit argument.
Expand Down Expand Up @@ -91,6 +93,19 @@ def __init__(self, of_type, *args, **kwargs):
graphene.String,
description=_("Filter the results using Wagtail's search."),
)
kwargs["search_operator"] = graphene.Argument(
graphene.Enum("SearchOperatorEnum", ["and", "or"]),
description=_(
"Specify search operator (and/or), see: https://docs.wagtail.org/en/stable/topics/search/searching.html#search-operator"
),
default_value="and",
)
kwargs["search_field"] = graphene.Argument(
graphene.List(graphene.String),
description=_(
"A list of fields to search in. see: https://docs.wagtail.org/en/stable/topics/search/searching.html#specifying-the-fields-to-search"
),
)

if "id" not in kwargs:
kwargs["id"] = graphene.Argument(graphene.ID, description=_("Filter by ID"))
Expand Down Expand Up @@ -198,6 +213,19 @@ def PaginatedQuerySet(of_type, type_class, **kwargs):
kwargs["search_query"] = graphene.Argument(
graphene.String, description=_("Filter the results using Wagtail's search.")
)
kwargs["search_operator"] = graphene.Argument(
graphene.Enum("SearchOperatorEnum", ["and", "or"]),
description=_(
"Specify search operator (and/or), see: https://docs.wagtail.org/en/stable/topics/search/searching.html#search-operator"
),
default_value="and",
)
kwargs["search_field"] = graphene.Argument(
graphene.List(graphene.String),
description=_(
"A list of fields to search in. see: https://docs.wagtail.org/en/stable/topics/search/searching.html#specifying-the-fields-to-search"
),
)

if "id" not in kwargs:
kwargs["id"] = graphene.Argument(graphene.ID, description=_("Filter by ID"))
Expand Down
46 changes: 41 additions & 5 deletions grapple/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from wagtail.models import Site
from wagtail.search.index import class_is_indexed
from wagtail.search.models import Query
from wagtail.search.utils import parse_query_string

from .settings import grapple_settings
from .types.structures import BasePaginatedType, PaginationType
Expand Down Expand Up @@ -62,6 +63,8 @@ def resolve_queryset(
id=None,
order=None,
collection=None,
search_operator="and",
search_fields=None,
**kwargs,
):
"""
Expand All @@ -83,6 +86,11 @@ def resolve_queryset(
:type order: str
:param collection: Use Wagtail's collection id to filter images or documents
:type collection: int
:param search_operator: The operator to use when combining search terms.
Defaults to "and".
:type search_operator: "and" | "or"
:param search_fields: A list of fields to search. Defaults to all fields.
:type search_fields: list
"""

if id is not None:
Expand Down Expand Up @@ -112,7 +120,14 @@ def resolve_queryset(
query = Query.get(search_query)
query.add_hit()

qs = qs.search(search_query, order_by_relevance=order_by_relevance)
filters, parsed_query = parse_query_string(search_query, search_operator)

qs = qs.search(
parsed_query,
order_by_relevance=order_by_relevance,
operator=search_operator,
fields=search_fields,
)
if connection.vendor != "sqlite":
qs = qs.annotate_score("search_score")

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


def resolve_paginated_queryset(
qs, info, page=None, per_page=None, search_query=None, id=None, order=None, **kwargs
qs,
info,
page=None,
per_page=None,
id=None,
order=None,
search_query=None,
search_operator="and",
search_fields=None,
**kwargs,
):
"""
Add page, per_page and search capabilities to the query. This contains
Expand All @@ -167,11 +191,16 @@ def resolve_paginated_queryset(
:type id: int
:param per_page: The maximum number of items to include on a page.
:type per_page: int
:param order: Order the query set using the Django QuerySet order_by format.
:type order: str
:param search_query: Using Wagtail search, exclude objects that do not match
the search query.
:type search_query: str
:param order: Order the query set using the Django QuerySet order_by format.
:type order: str
:param search_operator: The operator to use when combining search terms.
Defaults to "and".
:type search_operator: "and" | "or"
:param search_fields: A list of fields to search. Defaults to all fields.
:type search_fields: list
"""
page = int(page or 1)
per_page = min(
Expand Down Expand Up @@ -199,7 +228,14 @@ def resolve_paginated_queryset(
query = Query.get(search_query)
query.add_hit()

qs = qs.search(search_query, order_by_relevance=order_by_relevance)
filters, parsed_query = parse_query_string(search_query, search_operator)

qs = qs.search(
parsed_query,
order_by_relevance=order_by_relevance,
operator=search_operator,
fields=search_fields,
)
if connection.vendor != "sqlite":
qs = qs.annotate_score("search_score")

Expand Down

0 comments on commit 3bf9d79

Please sign in to comment.