Skip to content

Commit

Permalink
feature: add suggestedFilterOperator
Browse files Browse the repository at this point in the history
suggested property paths come with a suggested filter operator
  • Loading branch information
aaxelb committed Sep 8, 2023
1 parent 3fa5e31 commit aef9b4d
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 42 deletions.
26 changes: 16 additions & 10 deletions share/search/search_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
suggested_property_paths,
OSFMAP_VOCAB,
)
from trove.vocab.namespaces import RDF
from trove.vocab.trove import trove_labeler
from trove.vocab.namespaces import RDF, TROVE


logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -143,14 +144,19 @@ def _from_fuzzy_wordgroup(cls, each_word_negated: bool, words: typing.Iterable[s
@dataclasses.dataclass(frozen=True)
class SearchFilter:
class FilterOperator(enum.Enum):
# TODO: use iris from TROVE IriNamespace
ANY_OF = 'any-of'
NONE_OF = 'none-of'
IS_PRESENT = 'is-present'
IS_ABSENT = 'is-absent'
BEFORE = 'before'
AFTER = 'after'
AT_DATE = 'at-date'
# iri values
ANY_OF = TROVE['any-of']
NONE_OF = TROVE['none-of']
IS_PRESENT = TROVE['is-present']
IS_ABSENT = TROVE['is-absent']
BEFORE = TROVE['before']
AFTER = TROVE['after']
AT_DATE = TROVE['at-date']

@classmethod
def from_shortname(cls, shortname):
_iri = trove_labeler.iri_for_label(shortname)
return cls(_iri)

def is_date_operator(self):
return self in (self.BEFORE, self.AFTER, self.AT_DATE)
Expand Down Expand Up @@ -191,7 +197,7 @@ def from_filter_param(cls, param_name: QueryparamName, param_value: str):
else: # given operator
if _operator_value:
try:
_operator = SearchFilter.FilterOperator(_operator_value)
_operator = SearchFilter.FilterOperator.from_shortname(_operator_value)
except ValueError:
raise ValueError(f'unrecognized search-filter operator "{_operator_value}"')
_propertypath = tuple(
Expand Down
30 changes: 18 additions & 12 deletions trove/trovesearch_gathering.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
from trove.render.jsonld import RdfJsonldRenderer
from trove.util.queryparams import QUERYPARAM_VALUES_DELIM
from trove.vocab.namespaces import RDF, FOAF, DCTERMS, RDFS
from trove.vocab.osfmap import osfmap_labeler, OSFMAP_VOCAB
from trove.vocab.osfmap import osfmap_labeler, OSFMAP_VOCAB, suggested_filter_operator
from trove.vocab.trove import (
TROVE,
TROVE_API_VOCAB,
trove_indexcard_namespace,
trove_labeler,
JSONAPI_LINK_OBJECT,
JSONAPI_MEMBERNAME,
)
Expand Down Expand Up @@ -80,7 +81,9 @@ def gather_valuesearch_filter(focus, *, specific_index, search_params):
)
def gather_cardsearch(focus, *, specific_index, search_params):
assert isinstance(search_params, CardsearchParams)
# defer to the IndexStrategy implementation to do the search
_cardsearch_resp = specific_index.pls_handle_cardsearch(search_params)
# resulting index-cards
yield (TROVE.totalResultCount, _cardsearch_resp.total_result_count)
_result_page = []
for _result in _cardsearch_resp.search_result_page:
Expand All @@ -100,19 +103,19 @@ def gather_cardsearch(focus, *, specific_index, search_params):
*_text_evidence_twoples,
)))
yield (TROVE.searchResultPage, primitive_rdf.sequence(_result_page))
# links to more pages of results
yield from _search_page_links(focus, search_params, _cardsearch_resp)
_relatedproperty_list = []
for _propertypath in search_params.related_property_paths:
try:
_count = next(
_prop_result.usage_count
for _prop_result in _cardsearch_resp.related_propertypath_results
if _prop_result.property_path == _propertypath
)
except StopIteration:
_count = 0
_relatedproperty_list.append(_related_property_result(_propertypath, _count))
# info about related properties (for refining/filtering further)
_prop_usage_counts = {
_prop_result.property_path: _prop_result.usage_count
for _prop_result in _cardsearch_resp.related_propertypath_results
}
_relatedproperty_list = [
_related_property_result(_propertypath, _prop_usage_counts.get(_propertypath, 0))
for _propertypath in search_params.related_property_paths
]
yield (TROVE.relatedPropertyList, primitive_rdf.sequence(_relatedproperty_list))
# filter-values from search params, with any additional info
_valueinfo_by_iri = {}
for _filtervalue in _cardsearch_resp.filtervalue_info:
_value_info = _valuesearch_result_as_json(_filtervalue)
Expand Down Expand Up @@ -285,6 +288,9 @@ def _related_property_result(property_path: tuple[str, ...], count: int):
return frozenset((
(RDF.type, TROVE.RelatedPropertypath),
(TROVE.cardsearchResultCount, count),
(TROVE.suggestedFilterOperator, trove_labeler.label_for_iri(
suggested_filter_operator(property_path[-1]),
)),
*_propertypath_twoples(property_path),
))

Expand Down
58 changes: 47 additions & 11 deletions trove/vocab/osfmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,18 @@

from trove.util.iri_labeler import IriLabeler
from trove.vocab.trove import JSONAPI_MEMBERNAME
from trove.vocab.namespaces import OSFMAP, DCTERMS, FOAF, OWL, RDF, RDFS, SKOS, DCMITYPE, DCAT
from trove.vocab.namespaces import (
DCAT,
DCMITYPE,
DCTERMS,
FOAF,
OSFMAP,
OWL,
RDF,
RDFS,
SKOS,
TROVE,
)


# TODO: define as turtle, load in trove.vocab.__init__?
Expand Down Expand Up @@ -770,6 +781,31 @@
)


SUGGESTED_PRESENCE_PROPERTIES = frozenset((
OSFMAP.hasAnalyticCodeResource,
OSFMAP.hasDataResource,
OSFMAP.hasMaterialsResource,
OSFMAP.hasPapersResource,
OSFMAP.hasPreregisteredAnalysisPlan,
OSFMAP.hasPreregisteredStudyDesign,
OSFMAP.hasSupplementalResource,
OSFMAP.isSupplementedBy,
OSFMAP.supplements,
))


DATE_PROPERTIES = frozenset((
DCTERMS.date,
DCTERMS.available,
DCTERMS.created,
DCTERMS.modified,
DCTERMS.dateCopyrighted,
DCTERMS.dateSubmitted,
DCTERMS.dateAccepted,
OSFMAP.dateWithdrawn,
))


def suggested_property_paths(type_iris: set[str]) -> tuple[tuple[str, ...]]:
if not type_iris or not type_iris.issubset(OSFMAP_NORMS.focustype_iris):
return ()
Expand All @@ -786,15 +822,15 @@ def suggested_property_paths(type_iris: set[str]) -> tuple[tuple[str, ...]]:
return ALL_SUGGESTED_PROPERTY_PATHS


def suggested_filter_operator(property_iri: str):
# return iri value for the suggested trove-search filter operator
if is_date_property(property_iri):
return TROVE['at-date']
if property_iri in SUGGESTED_PRESENCE_PROPERTIES:
return TROVE['is-present']
return TROVE['any-of']


def is_date_property(property_iri):
# TODO: better inference (rdfs:range?)
return property_iri in {
DCTERMS.date,
DCTERMS.available,
DCTERMS.created,
DCTERMS.modified,
DCTERMS.dateCopyrighted,
DCTERMS.dateSubmitted,
DCTERMS.dateAccepted,
OSFMAP.dateWithdrawn,
}
return property_iri in DATE_PROPERTIES
35 changes: 26 additions & 9 deletions trove/vocab/trove.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,16 @@
primitive_rdf.text('filterValueSet', language_tag='en'),
},
},
TROVE.iriValue: {
TROVE.cardsearchResultCount: {
RDF.type: {RDF.Property, OWL.FunctionalProperty, JSONAPI_ATTRIBUTE},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('iriValue', language_tag='en'),
primitive_rdf.text('cardSearchResultCount', language_tag='en'),
},
},
TROVE.cardsearchResultCount: {
TROVE.suggestedFilterOperator: {
RDF.type: {RDF.Property, OWL.FunctionalProperty, JSONAPI_ATTRIBUTE},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('cardSearchResultCount', language_tag='en'),
primitive_rdf.text('suggestedFilterOperator', language_tag='en'),
},
},

Expand Down Expand Up @@ -192,35 +192,52 @@

# values:
TROVE['ten-thousands-and-more']: {
RDF.type: {RDF.Property},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('ten-thousands-and-more', language_tag='en'),
},
},
TROVE['any-of']: {
RDF.type: {RDF.Property},
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('any-of', language_tag='en'),
},
},
TROVE['none-of']: {
RDF.type: {RDF.Property},
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('none-of', language_tag='en'),
},
},
TROVE['is-absent']: {
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('is-absent', language_tag='en'),
},
},
TROVE['is-present']: {
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('is-present', language_tag='en'),
},
},
TROVE.before: {
RDF.type: {RDF.Property},
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('before', language_tag='en'),
},
},
TROVE.after: {
RDF.type: {RDF.Property},
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('after', language_tag='en'),
},
},
TROVE['at-date']: {
RDF.type: {TROVE.FilterOperator},
JSONAPI_MEMBERNAME: {
primitive_rdf.text('at-date', language_tag='en'),
},
},

# other:
RDF.type: {
Expand Down

0 comments on commit aef9b4d

Please sign in to comment.