diff --git a/src/server/sparql/FacetValues.js b/src/server/sparql/FacetValues.js index 2499ca6d41f1312117947f2ade7215205d8a0ba4..0729eeb7fddea29566b54e11630cbb20c8885e6d 100644 --- a/src/server/sparql/FacetValues.js +++ b/src/server/sparql/FacetValues.js @@ -1,6 +1,10 @@ import { has } from 'lodash'; import { runSelectQuery } from './SparqlApi'; -import { endpoint, facetValuesQuery } from './SparqlQueriesGeneral'; +import { + endpoint, + facetValuesQuery, + facetValuesQueryTimespan +} from './SparqlQueriesGeneral'; import { prefixes } from './SparqlQueriesPrefixes'; import { facetConfigs } from './FacetConfigs'; import { generateFilter, generateSelectedFilter } from './Filters'; @@ -18,8 +22,20 @@ export const getFacet = ({ spatialFilters, textFilters }) => { - let q = facetValuesQuery; const facetConfig = facetConfigs[facetClass][facetID]; + // choose a query template: + let q = ''; + switch(facetConfig.type) { + case 'list': + case 'hierarchical': + q = facetValuesQuery; + break; + case 'timespan': + q = facetValuesQueryTimespan; + break; + default: + q = facetValuesQuery; + } let selectedBlock = '# no selections'; let selectedNoHitsBlock = '# no filters from other facets'; let filterBlock = '# no filters'; @@ -28,7 +44,6 @@ export const getFacet = ({ const hasFilters = uriFilters !== null || spatialFilters !== null || textFilters !== null; - if (hasFilters) { filterBlock = generateFilter({ facetClass: facetClass, @@ -40,72 +55,31 @@ export const getFacet = ({ inverse: false, }); } + // if this facet has previous selections, include them in the query if (uriFilters !== null && has(uriFilters, facetID)) { - const selectedFilter = generateSelectedFilter({ - selectedValues:uriFilters[facetID], - inverse: false + selectedBlock = generateSelectedBlock({ + facetID, + uriFilters + }); + selectedNoHitsBlock = generateSelectedNoHitsBlock({ + facetClass, + facetID, + uriFilters, + spatialFilters, + textFilters }); - selectedBlock = ` - OPTIONAL { - ${selectedFilter} - BIND(true AS ?selected_) - } - `; - const facetIDs = Object.keys(uriFilters); - // get selected values with no hits, only when there are filters from - // other facets - if (facetIDs.length > 1) { - const noHitsFilter = generateFilter({ - facetClass: facetClass, - uriFilters: uriFilters, - spatialFilters: spatialFilters, - textFilters: textFilters, - filterTarget: 'instance', - facetID: facetID, - inverse: true, - }); - selectedNoHitsBlock = ` - UNION - { - # facet values that have been selected but return no results - VALUES ?id { <${uriFilters[facetID].join('> <')}> } - ${noHitsFilter} - BIND(true AS ?selected_) - } - `; - } } if (facetConfig.type === 'hierarchical') { mapper = mapHierarchicalFacet; - const parentFilterStr = generateFilter({ - facetClass: facetClass, - uriFilters: uriFilters, - spatialFilters: spatialFilters, - textFilters: textFilters, - filterTarget: 'instance2', - facetID: facetID, - inverse: false + const { parentPredicate } = facetConfig; + parentBlock = generateParentBlock({ + facetClass, + facetID, + uriFilters, + spatialFilters, + textFilters, + parentPredicate }); - let ignoreSelectedValues = ''; - if (uriFilters !== null && has(uriFilters, facetID)) { - ignoreSelectedValues = generateSelectedFilter({ - selectedValues:uriFilters[facetID], - inverse: true - }); - } - parentBlock = ` - UNION - # parents for all facet values - { - ${parentFilterStr} - # these instances should not be counted, so use another variable name - ?instance2 ${facetConfig.parentPredicate} ?id . - VALUES ?facetClass { <FACET_CLASS> } - ?instance2 a ?facetClass . - BIND(false AS ?selected_) - ${ignoreSelectedValues} - } - `; } q = q.replace('<SELECTED_VALUES>', selectedBlock); q = q.replace('<SELECTED_VALUES_NO_HITS>', selectedNoHitsBlock); @@ -115,8 +89,92 @@ export const getFacet = ({ q = q.replace(/<FACET_CLASS>/g, facetConfigs[facetClass].facetClass); q = q.replace(/<FILTER>/g, filterBlock ); q = q.replace(/<PREDICATE>/g, facetConfig.predicate); - // if (facetID == 'productionPlace') { - // console.log(prefixes + q) - // } return runSelectQuery(prefixes + q, endpoint, mapper); }; + +const generateSelectedBlock = ({ + facetID, + uriFilters, +}) => { + const selectedFilter = generateSelectedFilter({ + selectedValues: uriFilters[facetID], + inverse: false + }); + return ` + OPTIONAL { + ${selectedFilter} + BIND(true AS ?selected_) + } + `; +}; + +const generateSelectedNoHitsBlock = ({ + facetClass, + facetID, + uriFilters, + spatialFilters, + textFilters +}) => { + const facetIDs = Object.keys(uriFilters); + // get selected values with no hits, only when there are filters from + // other facets + if (facetIDs.length > 1) { + const noHitsFilter = generateFilter({ + facetClass: facetClass, + uriFilters: uriFilters, + spatialFilters: spatialFilters, + textFilters: textFilters, + filterTarget: 'instance', + facetID: facetID, + inverse: true, + }); + return ` + UNION + { + # facet values that have been selected but return no results + VALUES ?id { <${uriFilters[facetID].join('> <')}> } + ${noHitsFilter} + BIND(true AS ?selected_) + } + `; + } +}; + +const generateParentBlock = ({ + facetClass, + facetID, + uriFilters, + spatialFilters, + textFilters, + parentPredicate +}) => { + const parentFilterStr = generateFilter({ + facetClass: facetClass, + uriFilters: uriFilters, + spatialFilters: spatialFilters, + textFilters: textFilters, + filterTarget: 'instance2', + facetID: facetID, + inverse: false + }); + let ignoreSelectedValues = ''; + if (uriFilters !== null && has(uriFilters, facetID)) { + ignoreSelectedValues = generateSelectedFilter({ + selectedValues:uriFilters[facetID], + inverse: true + }); + } + return ` + UNION + # parents for all facet values + { + ${parentFilterStr} + # these instances should not be counted, so use another variable name + ?instance2 ${parentPredicate} ?id . + VALUES ?facetClass { <FACET_CLASS> } + ?instance2 a ?facetClass . + BIND(false AS ?selected_) + ${ignoreSelectedValues} + } + `; +}; diff --git a/src/server/sparql/SparqlQueriesGeneral.js b/src/server/sparql/SparqlQueriesGeneral.js index 6dc637f36a6def82e4fd626cf1627f56126cfecf..6142c5ea9ae7fa3f1afde918fd212d30d47cc305 100644 --- a/src/server/sparql/SparqlQueriesGeneral.js +++ b/src/server/sparql/SparqlQueriesGeneral.js @@ -97,7 +97,7 @@ export const facetValuesQuery = ` <ORDER_BY> `; -export const timespanFacetQuery = ` +export const facetValuesQueryTimespan = ` SELECT ?min ?max { <FILTER> ?instance <PREDICATE> ?timespan .