Skip to content
Snippets Groups Projects
FacetValues.js 5.82 KiB
Newer Older
import { runSelectQuery } from './SparqlApi';
import { has } from 'lodash';
import {
  endpoint,
  facetValuesQuery,
  facetValuesQueryTimespan,
  facetValuesRange
} from './SparqlQueriesGeneral';
import { prefixes } from './SparqlQueriesPrefixes';
esikkala's avatar
esikkala committed
import { facetConfigs } from './FacetConfigsMMM';
import {
  hasPreviousSelections,
  hasPreviousSelectionsFromOtherFacets,
  getUriFilters,
  generateConstraintsBlock,
  generateSelectedFilter
} from './Filters';
esikkala's avatar
esikkala committed
import {
  mapFacet,
  mapHierarchicalFacet,
  mapTimespanFacet
esikkala's avatar
esikkala committed
} from './Mappers';

esikkala's avatar
esikkala committed
export const getFacet = async ({
  facetClass,
  facetID,
  sortBy,
  sortDirection,
  resultFormat
  const facetConfig = facetConfigs[facetClass][facetID];
  // choose query template and result mapper:
  let mapper = null;
  switch(facetConfig.type) {
    case 'list':
      q = facetValuesQuery;
      mapper = mapFacet;
      break;
    case 'hierarchical':
      q = facetValuesQuery;
      mapper = mapHierarchicalFacet;
      break;
    case 'timespan':
      q = facetValuesQueryTimespan;
      mapper = mapTimespanFacet;
    case 'integer':
      q = facetValuesRange;
      mapper = mapTimespanFacet;
      break;
    default:
      q = facetValuesQuery;
      mapper = mapFacet;
esikkala's avatar
esikkala committed
  let selectedBlock = '# no selections';
esikkala's avatar
esikkala committed
  let selectedNoHitsBlock = '# no filters from other facets';
esikkala's avatar
esikkala committed
  let filterBlock = '# no filters';
  let parentBlock = '# no parents';
  let parentsForFacetValues = '# no parents for facet values';
  if (constraints !== null) {
    filterBlock = generateConstraintsBlock({
      facetClass: facetClass,
      constraints: constraints,
      filterTarget: 'instance',
      facetID: facetID,
      inverse: false,
    // if this facet has previous selections, include them in the query
    if (hasPreviousSelections(constraints, facetID)) {
      selectedBlock = generateSelectedBlock({
      /* if there are also filters from other facets, we need this
         additional block for facet values that return 0 hits */
      if (hasPreviousSelectionsFromOtherFacets(constraints, facetID)) {
        selectedNoHitsBlock = generateSelectedNoHitsBlock({
          facetClass,
          facetID,
          constraints
        });
      }
esikkala's avatar
esikkala committed
  }
  if (facetConfig.type === 'hierarchical') {
    const { parentPredicate } = facetConfig;
    parentBlock = generateParentBlock({
      facetClass,
      facetID,
esikkala's avatar
esikkala committed
    });
    parentsForFacetValues = `
      OPTIONAL { ?id ${facetConfig.parentProperty} ?parent_ }
      BIND(COALESCE(?parent_, '0') as ?parent)
    `;
  q = q.replace('<SELECTED_VALUES>', selectedBlock);
  q = q.replace('<SELECTED_VALUES_NO_HITS>', selectedNoHitsBlock);
esikkala's avatar
esikkala committed
  q = q.replace(/<FACET_VALUE_FILTER>/g, facetConfig.facetValueFilter);
  q = q.replace(/<FACET_LABEL_FILTER>/g,
esikkala's avatar
esikkala committed
    has(facetConfig, 'facetLabelFilter')
      ? facetConfig.facetLabelFilter
      : ''
  );
esikkala's avatar
esikkala committed
  q = q.replace('<PARENTS>', parentBlock);
  q = q.replace('<PARENTS_FOR_FACET_VALUES>', parentsForFacetValues);
  if (facetConfig.type === 'list') {
    q = q.replace('<ORDER_BY>', `ORDER BY ${sortDirection}(?${sortBy})` );
  } else {
    q = q.replace('<ORDER_BY>', '# no need for ordering');
  }
esikkala's avatar
esikkala committed
  q = q.replace(/<FACET_CLASS>/g, facetConfigs[facetClass].facetClass);
  q = q.replace(/<FILTER>/g, filterBlock );
  q = q.replace(/<PREDICATE>/g, facetConfig.predicate);
  if (facetConfig.type === 'timespan') {
    q = q.replace('<START_PROPERTY>', facetConfig.startProperty);
    q = q.replace('<END_PROPERTY>', facetConfig.endProperty);
  }
  // console.log(prefixes + q)
esikkala's avatar
esikkala committed
  const response = await runSelectQuery(prefixes + q, endpoint, mapper, resultFormat);
  if (facetConfig.type === 'hierarchical') {
    return({
      facetClass: facetClass,
      id: facetID,
      data: response.data.treeData,
      flatData: response.data.flatData,
      sparqlQuery: response.sparqlQuery
    });
  } else {
    return({
      facetClass: facetClass,
      id: facetID,
      data: response.data,
      sparqlQuery: response.sparqlQuery
    });
  }

const generateSelectedBlock = ({
  facetID,
}) => {
  const selectedFilter = generateSelectedFilter({
    inverse: false
  });
  return `
          OPTIONAL {
            ${selectedFilter}
            BIND(true AS ?selected_)
          }
  `;
};

const generateSelectedNoHitsBlock = ({
  facetClass,
  facetID,
  const noHitsFilter = generateConstraintsBlock({
    facetClass: facetClass,
    constraints: constraints,
    filterTarget: 'instance',
    facetID: facetID,
    inverse: true,
  });
  return `
  UNION
  {
  # facet values that have been selected but return no results
    VALUES ?id { <${getUriFilters(constraints, facetID).join('> <')}> }
    ${noHitsFilter}
    BIND(true AS ?selected_)
  }
    `;
};

const generateParentBlock = ({
  facetClass,
  facetID,
  let parentFilterStr = '# no filters';
  let ignoreSelectedValues = '# no selected values';
  if (constraints !== null) {
    parentFilterStr = generateConstraintsBlock({
      facetClass: facetClass,
      constraints: constraints,
      filterTarget: 'instance2',
      facetID: facetID,
      inverse: false
    if (hasPreviousSelections) {
      ignoreSelectedValues = generateSelectedFilter({
        facetID: facetID,
        constraints: constraints,
        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}
        }
    `;
};