Skip to content
Open
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
5 changes: 5 additions & 0 deletions client/public/config/config_ecoforcast.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ FACETS:
sort: acs
open: true
type: range
- field: variableMeasured
title: Variables Measured
sort: acs
open: true
type: propertyvalue
ORDER_BY_DEFAULT: score
ORDER_BY_OPTIONS:
- field: name
Expand Down
10 changes: 5 additions & 5 deletions client/public/config/config_qlever.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ FACETS:
sort: acs
open: true
type: rangeyear
# - field: variableMeasured
# title: Variables Measured
# sort: acs
# open: true
# type: text
- field: variableMeasured
title: Variables Measured
sort: acs
open: true
type: propertyvalue
ORDER_BY_DEFAULT: score
ORDER_BY_OPTIONS:
- field: name
Expand Down
13 changes: 8 additions & 5 deletions client/src/services/SearchService.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,10 +278,6 @@ SELECT ?value (0 as ?count) WHERE { FILTER(false) } LIMIT 0
resourceType = '',
} = searchContext;

const sparqlProperty =
facetConfig.sparql_property ||
this.queryBuilder.getDefaultSparqlProperty(field);

// Exclude this facet's own filters to avoid self-filtering options
const filtersCopy = { ...(currentFilters || {}) };
delete filtersCopy[field];
Expand All @@ -297,7 +293,14 @@ WHERE {
resourceType,
filtersCopy
);
q += this.queryBuilder.buildFacetPropertyPattern(field, sparqlProperty);
if (facetConfig.type === 'variablemeasured' || facetConfig.type === 'propertyvalue') {
q += this.queryBuilder.buildPropertyValueNamePattern(field, facetConfig);
} else {
const sparqlProperty =
facetConfig.sparql_property ||
this.queryBuilder.getDefaultSparqlProperty(field);
q += this.queryBuilder.buildFacetPropertyPattern(field, sparqlProperty);
}
q += `}
GROUP BY ?value
ORDER BY DESC(?count) ?value
Expand Down
47 changes: 47 additions & 0 deletions client/src/services/SparqlQueryBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -437,6 +437,10 @@ ${inner}
case 'text':
fragments += this.buildTextFilter(field, Array.isArray(values) ? values : [values], facetConfig);
break;
case 'variablemeasured':
case 'propertyvalue':
fragments += this.buildPropertyValueNameFilter(field, Array.isArray(values) ? values : [values], facetConfig);
break;
case 'range':
case 'rangeyear':
case 'rangedepth':
Expand Down Expand Up @@ -758,6 +762,49 @@ ${typeValues}${typeFilter}${textFilters}${rangeConstraints} }
return { north: n, south: s, east: e, west: w };
}

/**
* Generic filter for any schema property that points to a PropertyValue node,
* matching on schema:name using CONTAINS (case-insensitive).
*
* The SPARQL property path is taken from facetConfig.sparql_property; it defaults
* to schema:variableMeasured so that "variableMeasured" facets work out of the box.
* Other PropertyValue relationships (e.g. schema:measurementTechnique) can be
* supported by adding a new facet entry in config with the desired sparql_property.
*
* Values are sanitized via escapeValue (backslash and double-quote escaping).
*/
buildPropertyValueNameFilter(field, values, facetConfig) {
if (!Array.isArray(values) || values.length === 0) return '';
const pvProperty =
facetConfig?.sparql_property || 'schema:variableMeasured|sschema:variableMeasured';
const nodeVar = `${field}_pv`;
const typeVar = `${field}_pvType`;
const nameVar = `${field}_pvName`;
const containsExprs = values
.map(v => `CONTAINS(LCASE(STR(?${nameVar})), LCASE("${this.escapeValue(v)}"))`)
.join(' || ');
return ` ?subj ${pvProperty} ?${nodeVar} .
VALUES ?${typeVar} { schema:PropertyValue sschema:PropertyValue }
?${nodeVar} a ?${typeVar} .
?${nodeVar} schema:name|sschema:name ?${nameVar} .
FILTER(${containsExprs}) .\n`;
}

/**
* Triple pattern that binds ?value to distinct PropertyValue names for facet option lists.
* Uses facetConfig.sparql_property (defaults to schema:variableMeasured).
*/
buildPropertyValueNamePattern(field, facetConfig) {
const pvProperty =
facetConfig?.sparql_property || 'schema:variableMeasured|sschema:variableMeasured';
const nodeVar = `${field}_pv_opt`;
const typeVar = `${field}_pvType_opt`;
return ` ?subj ${pvProperty} ?${nodeVar} .
VALUES ?${typeVar} { schema:PropertyValue sschema:PropertyValue }
?${nodeVar} a ?${typeVar} .
?${nodeVar} schema:name|sschema:name ?value .\n`;
}

buildGenericFilter(field, values, facetConfig) {
const sparqlProperty = facetConfig.sparql_property || this.getDefaultSparqlProperty(field);
if (!Array.isArray(values) || values.length === 0) return '';
Expand Down
Loading