From b838e57f55385f60c2f2288f03935e5621b5602c Mon Sep 17 00:00:00 2001 From: david Date: Thu, 15 Aug 2024 10:52:41 +1000 Subject: [PATCH 1/2] fix: search counts behave the same as other counts; returns a string with the number of results or if at the limit=n+1 then ">n" as a string --- prez/config.py | 1 + prez/dependencies.py | 4 ++-- prez/services/listings.py | 7 ++++++- prez/services/query_generation/search.py | 24 ++++++++++++++++-------- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/prez/config.py b/prez/config.py index b1df20ac..eadccdf9 100755 --- a/prez/config.py +++ b/prez/config.py @@ -40,6 +40,7 @@ class Settings(BaseSettings): system_uri: Optional[str] = f"{protocol}://{host}:{port}" order_lists_by_label: bool = True listing_count_limit: int = 1000 + search_count_limit: int = 10 label_predicates: Optional[List[URIRef]] = [ SKOS.prefLabel, DCTERMS.title, diff --git a/prez/dependencies.py b/prez/dependencies.py index 679309ee..7581b39a 100755 --- a/prez/dependencies.py +++ b/prez/dependencies.py @@ -171,8 +171,8 @@ async def generate_search_query(request: Request): escaped_term = escape_for_lucene_and_sparql(term) predicates = request.query_params.getlist("predicates") page = request.query_params.get("page", 1) - per_page = request.query_params.get("per_page", 10) - limit = int(per_page) + per_page = request.query_params.get("per_page") + limit = int(per_page) if per_page else settings.search_count_limit offset = limit * (int(page) - 1) return SearchQueryRegex( diff --git a/prez/services/listings.py b/prez/services/listings.py index 5598b7c2..8e8ea6a9 100755 --- a/prez/services/listings.py +++ b/prez/services/listings.py @@ -7,6 +7,7 @@ from sparql_grammar_pydantic import IRI, Var, TriplesSameSubject from prez.cache import endpoints_graph_cache +from prez.config import settings from prez.reference_data.prez_ns import PREZ, ALTREXT, ONT from prez.renderers.renderer import return_from_graph from prez.services.link_generation import add_prez_links @@ -98,7 +99,11 @@ async def listing_function( # count search results - hard to do in SPARQL as the SELECT part of the query is NOT aggregated if search_query: count = len(list(item_graph.subjects(RDF.type, PREZ.SearchResult))) - item_graph.add((PREZ.SearchResult, PREZ["count"], Literal(count))) + if count == settings.search_count_limit: + count_literal = f">{count-1}" + else: + count_literal = f"{count}" + item_graph.add((PREZ.SearchResult, PREZ["count"], Literal(count_literal))) return await return_from_graph( item_graph, pmts.selected["mediatype"], diff --git a/prez/services/query_generation/search.py b/prez/services/query_generation/search.py index fab138ae..4fa3ad94 100755 --- a/prez/services/query_generation/search.py +++ b/prez/services/query_generation/search.py @@ -46,25 +46,25 @@ class SearchQueryRegex(ConstructQuery): - limit: int = 10 # specify here to make available as attribute - offset: int = 0 # specify here to make available as attribute - def __init__( self, term: str, predicates: Optional[List[str]] = None, - limit: int = 10, - offset: int = 0, + limit: int = None, + offset: int = None, ): + + limit += 1 # increase the limit by one so we know if there are further pages of results. + + if not predicates: + predicates = settings.default_search_predicates + sr_uri: Var = Var(value="focus_node") pred: Var = Var(value="pred") match: Var = Var(value="match") weight: Var = Var(value="weight") hashid: Var = Var(value="hashID") - if not predicates: - predicates = settings.default_search_predicates - ct_map = { IRI(value=PREZ.searchResultWeight): weight, IRI(value=PREZ.searchResultPredicate): pred, @@ -376,3 +376,11 @@ def order_by(self): @property def order_by_direction(self): return "DESC" + + @property + def limit(self): + return self.where_clause.group_graph_pattern.content.solution_modifier.limit_offset.limit_clause.limit + + @property + def offset(self): + return self.where_clause.group_graph_pattern.content.solution_modifier.limit_offset.offset_clause.offset From 26b05c623c06ec730786ee52c72e862ec6e5197c Mon Sep 17 00:00:00 2001 From: david Date: Thu, 15 Aug 2024 11:09:18 +1000 Subject: [PATCH 2/2] fix: limit and offset are required params for SearchQueryRegex; specify them in test. Fix checking of result count to be against the SearchQueryRegex limit in order to account for both QSA and default limits. --- prez/services/listings.py | 2 +- prez/services/query_generation/search.py | 4 ++-- tests/test_query_construction.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/prez/services/listings.py b/prez/services/listings.py index 8e8ea6a9..d14fb954 100755 --- a/prez/services/listings.py +++ b/prez/services/listings.py @@ -99,7 +99,7 @@ async def listing_function( # count search results - hard to do in SPARQL as the SELECT part of the query is NOT aggregated if search_query: count = len(list(item_graph.subjects(RDF.type, PREZ.SearchResult))) - if count == settings.search_count_limit: + if count == search_query.limit: count_literal = f">{count-1}" else: count_literal = f"{count}" diff --git a/prez/services/query_generation/search.py b/prez/services/query_generation/search.py index 4fa3ad94..b4bbb20a 100755 --- a/prez/services/query_generation/search.py +++ b/prez/services/query_generation/search.py @@ -49,9 +49,9 @@ class SearchQueryRegex(ConstructQuery): def __init__( self, term: str, + limit: int, + offset: int, predicates: Optional[List[str]] = None, - limit: int = None, - offset: int = None, ): limit += 1 # increase the limit by one so we know if there are further pages of results. diff --git a/tests/test_query_construction.py b/tests/test_query_construction.py index afbd57da..c1693175 100755 --- a/tests/test_query_construction.py +++ b/tests/test_query_construction.py @@ -102,7 +102,7 @@ def test_basic_listing(): def test_search_query_regex(): - sq = SearchQueryRegex(term="test", predicates=[RDFS.label]) + sq = SearchQueryRegex(term="test", predicates=[RDFS.label], limit=10, offset=0) test = PrezQueryConstructor( profile_triples=[ TriplesSameSubjectPath.from_spo(