Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

subjects: improve search with CompositeSuggestQueryParser #448

Merged
merged 1 commit into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions invenio_vocabularies/contrib/subjects/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@
from invenio_i18n import lazy_gettext as _
from invenio_records_resources.services import SearchOptions
from invenio_records_resources.services.records.components import DataComponent
from invenio_records_resources.services.records.queryparser import (
CompositeSuggestQueryParser,
)
from werkzeug.local import LocalProxy

from ...services.components import PIDComponent
from ...services.querystr import FilteredSuggestQueryParser

subject_schemes = LocalProxy(
lambda: current_app.config["VOCABULARIES_SUBJECTS_SCHEMES"]
Expand All @@ -38,9 +40,8 @@
class SubjectsSearchOptions(SearchOptions):
"""Search options."""

suggest_parser_cls = FilteredSuggestQueryParser.factory(
filter_field="scheme",
fields=[ # suggest fields
suggest_parser_cls = CompositeSuggestQueryParser.factory(
fields=[
"subject^100",
localized_title,
"synonyms^20",
Expand Down
5 changes: 5 additions & 0 deletions invenio_vocabularies/services/querystr.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

"""Querystring parsing."""

import warnings
from functools import partial

from invenio_records_resources.services.records.params import SuggestQueryParser
Expand All @@ -20,6 +21,10 @@ class FilteredSuggestQueryParser(SuggestQueryParser):
@classmethod
def factory(cls, filter_field=None, **extra_params):
"""Create a prepared instance of the query parser."""
warnings.warn(
"FilteredSuggestQueryParser is deprecated, use SuggestQueryParser or CompositeSuggestQueryParser instead",
DeprecationWarning,
)
return partial(cls, filter_field=filter_field, extra_params=extra_params)

def __init__(self, identity=None, filter_field=None, extra_params=None):
Expand Down
36 changes: 21 additions & 15 deletions tests/contrib/subjects/test_subjects_resource.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2021 CERN.
# Copyright (C) 2021-2024 CERN.
# Copyright (C) 2021 Northwestern University.
#
# Invenio-Vocabularies is free software; you can redistribute it and/or
Expand Down Expand Up @@ -129,22 +129,28 @@ def example_subjects(app, db, search_clear, identity, service):


def test_suggest(client, h, prefix, example_subjects):
"""Test FilteredSuggestParam."""
# No filter
"""Test the subjects query parser."""
# Full word
res = client.get(f"{prefix}?suggest=abdomen", headers=h)
assert res.json["hits"]["total"] == 4
# The less specific text appears at the end of the list
assert res.json["hits"]["hits"][3]["subject"] == "Abdomen, Acute"

# Incomplete word -> finds the same results
res = client.get(f"{prefix}?suggest=abdo", headers=h)
assert res.json["hits"]["total"] == 4

# Single filter
res = client.get(f"{prefix}?suggest=MeSH:abdo", headers=h)
assert res.status_code == 200
assert res.json["hits"]["total"] == 2
# Multiple words -> narrows down the results
res = client.get(f"{prefix}?suggest=abdomen%20acute", headers=h)
assert res.json["hits"]["total"] == 1
assert res.json["hits"]["hits"][0]["subject"] == "Abdomen, Acute"

# Multiple filters
res = client.get(f"{prefix}?suggest=MeSH,Other:abdo", headers=h)
assert res.status_code == 200
assert res.json["hits"]["total"] == 3
# Multiple words with incomplete last word -> still finds the same result
res = client.get(f"{prefix}?suggest=abdomen%20acu", headers=h)
assert res.json["hits"]["total"] == 1
assert res.json["hits"]["hits"][0]["subject"] == "Abdomen, Acute"

# Ignore non existing filter
res = client.get(f"{prefix}?suggest=MeSH,Foo:abdo", headers=h)
assert res.status_code == 200
assert res.json["hits"]["total"] == 2
# Multiple words with incomplete last word in other order -> still finds the same result
res = client.get(f"{prefix}?suggest=acute%20abdo", headers=h)
assert res.json["hits"]["total"] == 1
assert res.json["hits"]["hits"][0]["subject"] == "Abdomen, Acute"