diff --git a/share/search/index_strategy/_trovesearch_util.py b/share/search/index_strategy/_trovesearch_util.py index ed2e086f6..fbc09c8f3 100644 --- a/share/search/index_strategy/_trovesearch_util.py +++ b/share/search/index_strategy/_trovesearch_util.py @@ -148,7 +148,7 @@ def __post_init__(self): self.integer_values[_walk_path].add(_walk_obj) elif isinstance(_walk_obj, rdf.Literal): if XSD.integer in _walk_obj.datatype_iris: - self.integer_values[_walk_path].add(_walk_obj) + self.integer_values[_walk_path].add(int(_walk_obj.unicode_value)) if {RDF.string, RDF.langString}.intersection(_walk_obj.datatype_iris): self.text_values[_walk_path].add(_walk_obj) # try for date in a date property, regardless of the above diff --git a/tests/share/search/index_strategy/_common_trovesearch_tests.py b/tests/share/search/index_strategy/_common_trovesearch_tests.py index ac2ab2f27..81461a34e 100644 --- a/tests/share/search/index_strategy/_common_trovesearch_tests.py +++ b/tests/share/search/index_strategy/_common_trovesearch_tests.py @@ -142,12 +142,15 @@ def test_cardsearch_pagination(self): def test_cardsearch_related_properties(self): self._fill_test_data_for_querying() - _cardsearch_params = CardsearchParams.from_querystring('') - with mock.patch.object(_cardsearch_params, 'related_property_paths', new=( - (DCTERMS.creator,), - (DCTERMS.references,), - (BLARG.nada,), - )): + with mock.patch( + 'trove.trovesearch.search_params.suggested_property_paths', + return_value=( + (DCTERMS.creator,), + (DCTERMS.references,), + (BLARG.nada,), + ), + ): + _cardsearch_params = CardsearchParams.from_querystring('') _cardsearch_handle = self.current_index.pls_handle_cardsearch(_cardsearch_params) self.assertEqual(_cardsearch_handle.related_propertypath_results, [ PropertypathUsage((DCTERMS.creator,), 3), diff --git a/trove/render/jsonapi.py b/trove/render/jsonapi.py index 11e409d2b..e233fe1a4 100644 --- a/trove/render/jsonapi.py +++ b/trove/render/jsonapi.py @@ -157,7 +157,7 @@ def _resource_id_for_blanknode(self, blanknode: frozenset, /): _serializable_obj: Any if isinstance(_obj, primitive_rdf.Literal): _serializable_obj = [_obj.unicode_value, *sorted(_obj.datatype_iris)] - elif isinstance(_obj, str): + elif isinstance(_obj, (str, int, float)): _serializable_obj = _obj elif isinstance(_obj, frozenset): _serializable_obj = self._resource_id_for_blanknode(_obj) diff --git a/trove/trovesearch/search_params.py b/trove/trovesearch/search_params.py index 5e2a6b858..6670c1885 100644 --- a/trove/trovesearch/search_params.py +++ b/trove/trovesearch/search_params.py @@ -30,7 +30,7 @@ OSFMAP_THESAURUS, ) from trove.vocab.trove import trove_shorthand -from trove.vocab.namespaces import RDF, TROVE, OWL, NAMESPACES_SHORTHAND +from trove.vocab.namespaces import RDF, TROVE, OWL, NAMESPACES_SHORTHAND, FOAF, DCTERMS logger = logging.getLogger(__name__) @@ -59,6 +59,41 @@ ONE_GLOB_PROPERTYPATH: Propertypath = (GLOB_PATHSTEP,) DEFAULT_PROPERTYPATH_SET: PropertypathSet = frozenset([ONE_GLOB_PROPERTYPATH]) +DEFAULT_INCLUDES_BY_TYPE = { + TROVE.Cardsearch: { + (TROVE.searchResultPage,), + (TROVE.relatedPropertyList,), + }, + TROVE.Valuesearch: { + (TROVE.searchResultPage,), + }, + TROVE.SearchResult: { + (TROVE.indexCard,), + }, +} + +DEFAULT_FIELDS_BY_TYPE = { + TROVE.Indexcard: { + (TROVE.resourceMetadata,), + (TROVE.focusIdentifier,), + (DCTERMS.issued,), + (DCTERMS.modified,), + (FOAF.primaryTopic), + }, + TROVE.Cardsearch: { + (TROVE.totalResultCount,), + (TROVE.cardSearchText,), + (TROVE.cardSearchFilter,), + }, + TROVE.Valuesearch: { + (TROVE.propertyPath,), + (TROVE.valueSearchText,), + (TROVE.valueSearchFilter,), + (TROVE.cardSearchText,), + (TROVE.cardSearchFilter,), + }, +} + class ValueType(enum.Enum): # note: enum values are iris @@ -80,12 +115,6 @@ def to_shortname(self) -> str: return trove_shorthand().compact_iri(self.value) -class TrovesearchIncludePaths(enum.Enum): - # property-path values; correspond with expensive work could be skipped - CARDS = (TROVE.searchResultPage, TROVE.indexCard) - RELATED = (TROVE.relatedPropertyList,) - - ### # dataclasses for parsed search-api query parameters @@ -109,7 +138,7 @@ def parse_queryparams(cls, queryparams: QueryparamDict) -> dict: # subclasses should override and add their fields to super().parse_queryparams(queryparams) return { 'iri_shorthand': cls._gather_shorthand(queryparams), - 'include': cls._gather_include(queryparams), + 'include': frozenset(cls._gather_include(queryparams)), 'accept_mediatype': _get_single_value(queryparams, QueryparamName('acceptMediatype')), } @@ -138,11 +167,9 @@ def _gather_shorthand(cls, queryparams: QueryparamDict): @classmethod def _gather_include(cls, queryparams: QueryparamDict): - return frozenset( - itertools.chain.from_iterable( - _parse_propertypath_set(_include_value) - for _, _include_value in queryparams.get('include', []) - ) + return itertools.chain.from_iterable( + _parse_propertypath_set(_include_value) + for _, _include_value in queryparams.get('include', []) ) def get_next_streaming_params(self) -> typing.Self | None: @@ -497,11 +524,19 @@ def parse_queryparams(cls, queryparams: QueryparamDict) -> dict: 'page_cursor': _get_page_cursor(queryparams), } + @classmethod + def _gather_include(cls, queryparams: QueryparamDict): + _explicit_includes = set(super()._gather_include(queryparams)) + return itertools.chain( + _explicit_includes or DEFAULT_INCLUDES_BY_TYPE[TROVE.Cardsearch], + DEFAULT_FIELDS_BY_TYPE[TROVE.Cardsearch], + ) + @functools.cached_property def related_property_paths(self) -> tuple[Propertypath, ...]: return ( _get_related_property_paths(self.cardsearch_filter_set) - if TrovesearchIncludePaths.RELATED.value in self.include + if (TROVE.relatedPropertyList,) in self.include else () ) @@ -559,6 +594,14 @@ def parse_queryparams(cls, queryparams: QueryparamDict) -> dict: 'valuesearch_filter_set': SearchFilter.from_queryparam_family(queryparams, 'valueSearchFilter'), } + @classmethod + def _gather_include(cls, queryparams: QueryparamDict): + _explicit_includes = set(super()._gather_include(queryparams)) + return itertools.chain( + _explicit_includes or DEFAULT_INCLUDES_BY_TYPE[TROVE.Valuesearch], + DEFAULT_FIELDS_BY_TYPE[TROVE.Valuesearch], + ) + def __post_init__(self): if is_date_property(self.valuesearch_propertypath[-1]): # date-value limitations diff --git a/trove/views/search.py b/trove/views/search.py index 420a9a2ed..408b7010f 100644 --- a/trove/views/search.py +++ b/trove/views/search.py @@ -19,7 +19,6 @@ CardsearchFocus, ValuesearchFocus, ) -from trove.vocab.namespaces import TROVE, FOAF, DCTERMS from trove.render import ( DEFAULT_RENDERER_TYPE, get_renderer_type, @@ -36,42 +35,6 @@ _TrovesearchHandler = Callable[[BaseTroveParams], BasicSearchHandle] -DEFAULT_INCLUDES_BY_TYPE = { - TROVE.Cardsearch: { - TROVE.searchResultPage, - TROVE.relatedPropertyList, - }, - TROVE.Valuesearch: { - TROVE.searchResultPage, - }, - TROVE.SearchResult: { - TROVE.indexCard, - }, -} - -DEFAULT_FIELDS_BY_TYPE = { - TROVE.Indexcard: { - TROVE.resourceMetadata, - TROVE.focusIdentifier, - DCTERMS.issued, - DCTERMS.modified, - FOAF.primaryTopic - }, - TROVE.Cardsearch: { - TROVE.totalResultCount, - TROVE.cardSearchText, - TROVE.cardSearchFilter, - }, - TROVE.Valuesearch: { - TROVE.propertyPath, - TROVE.valueSearchText, - TROVE.valueSearchFilter, - TROVE.cardSearchText, - TROVE.cardSearchFilter, - }, -} - - class _BaseTrovesearchView(View, abc.ABC): # expected on inheritors focus_type: type[gather.Focus] @@ -96,8 +59,9 @@ def get(self, request): search_params=_search_params, search_handle=self.get_search_handle(_specific_index, _search_params), ) - # fill the gathering's cache with requested info - self._gather_as_requested(_search_gathering, _focus) + if _renderer_type.PASSIVE_RENDER: + # fill the gathering's cache with requested info + self._gather_as_requested(_search_gathering, _focus) # take gathered data into a response _renderer = _renderer_type(_focus, _search_gathering) return make_http_response( @@ -135,16 +99,7 @@ def get_search_handler( def _gather_as_requested(self, gathering, focus) -> None: _search_params: BaseTroveParams = gathering.gatherer_kwargs['search_params'] - if _search_params.include is not None: - gathering.ask(_search_params.include) - else: - for _type_iri in focus.type_iris: - try: - _include_paths = DEFAULT_INCLUDES_BY_TYPE[_type_iri] - except KeyError: - pass - else: - gathering.ask(_include_paths) + gathering.ask(_search_params.include) class CardsearchView(_BaseTrovesearchView): diff --git a/trove/vocab/trove.py b/trove/vocab/trove.py index bcc90c5d7..c8c2f377f 100644 --- a/trove/vocab/trove.py +++ b/trove/vocab/trove.py @@ -772,16 +772,16 @@ def trove_browse_link(iri: str): RDF.type: {RDF.Property, OWL.FunctionalProperty, JSONAPI_ATTRIBUTE}, JSONAPI_MEMBERNAME: {literal('suggestedFilterOperator', language='en')}, }, + TROVE.evidenceCardIdentifier: { + RDF.type: {RDF.Property, OWL.FunctionalProperty, JSONAPI_ATTRIBUTE}, + JSONAPI_MEMBERNAME: {literal('evidenceCardIdentifier', language='en')}, + }, # relationships: TROVE.searchResultPage: { RDF.type: {RDF.Property, JSONAPI_RELATIONSHIP}, JSONAPI_MEMBERNAME: {literal('searchResultPage', language='en')}, }, - TROVE.evidenceCardIdentifier: { - RDF.type: {RDF.Property, OWL.FunctionalProperty, JSONAPI_RELATIONSHIP}, - JSONAPI_MEMBERNAME: {literal('evidenceCardIdentifier', language='en')}, - }, TROVE.relatedPropertyList: { RDF.type: {RDF.Property, JSONAPI_RELATIONSHIP}, JSONAPI_MEMBERNAME: {literal('relatedProperties', language='en')},