UNPKG

@comunica/actor-rdf-join-entries-sort-traversal-zero-knowledge

Version:

A rdf-join-entries-sort actor that orders by increasing traversal-zero-knowledge

149 lines 7.31 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ActorRdfJoinEntriesSortTraversalZeroKnowledge = void 0; const bus_rdf_join_entries_sort_1 = require("@comunica/bus-rdf-join-entries-sort"); const context_entries_1 = require("@comunica/context-entries"); const core_1 = require("@comunica/core"); const utils_algebra_1 = require("@comunica/utils-algebra"); const utils_1 = require("@comunica/utils-algebra/lib/utils"); const rdf_terms_1 = require("rdf-terms"); /** * An actor that sorts join entries based on Hartig's heuristic for plan selection in link traversal environments. * * It first determines isolated connected graphs. (done by @comunica/actor-optimize-query-operation-join-connected) * For each of the connected graphs, it orders triple patterns in BGPs by the following priority: * 1. dependency-respecting: for each (non-first) pattern, at least one variable must occur in a preceding pattern. * 2. seed: try to make the first pattern contain a source URI. * 3. no vocab seed: avoid first triple pattern with vocab URI (variable predicate, * or variable objects with rdf:type predicate) * 4. filtering: patterns only containing variables also contained in preceding triple patterns * are placed as soon as possible. * * It does this in an adaptive way. * This means that this actor will only determine the first triple pattern, * execute it, and materialize the remaining BGP based on its results. * After that, the remaining BGP is evaluated recursively by this or another BGP actor. */ class ActorRdfJoinEntriesSortTraversalZeroKnowledge extends bus_rdf_join_entries_sort_1.ActorRdfJoinEntriesSort { constructor(args) { super(args); } /** * Obtain all IRIs from the given pattern that are not related to vocabularies. * Concretely, predicates will be omitted, and objects if predicate is http://www.w3.org/1999/02/22-rdf-syntax-ns#type * @param pattern A quad pattern. */ static getPatternNonVocabUris(pattern) { let nonVocabTerms; const predicates = []; if (pattern.type === 'pattern') { predicates.push(pattern.predicate); } else { utils_algebra_1.algebraUtils.visitOperation(pattern, { [utils_algebra_1.Algebra.Types.LINK]: { preVisitor: () => ({ continue: false }), visitor: (link) => { predicates.push(link.iri); return false; }, }, [utils_algebra_1.Algebra.Types.NPS]: { preVisitor: () => ({ continue: false }), visitor: (nps) => { for (const iri of nps.iris) { predicates.push(iri); } return false; }, }, }); } if (predicates .some(predicate => predicate.termType === 'NamedNode' && predicate.value === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type')) { nonVocabTerms = [pattern.subject, pattern.graph]; } else { nonVocabTerms = [pattern.subject, pattern.object, pattern.graph]; } return (0, rdf_terms_1.getNamedNodes)(nonVocabTerms); } /** * Determine the source IRI of a given IRI without hash. * @param namedNode An IRI. */ static getSourceUri(namedNode) { const value = namedNode.value; const hashPos = value.indexOf('#'); return hashPos > 0 ? value.slice(0, hashPos) : value; } /** * Calculate a score for the given quad pattern based on a given set of sources. * The more sources are present in the given pattern as non-vocab URIs, the higher the score. * @param pattern A quad pattern. * @param sources An array of sources. */ static getScoreSeedNonVocab(pattern, sources) { return ActorRdfJoinEntriesSortTraversalZeroKnowledge.getPatternNonVocabUris(pattern) .map(term => ActorRdfJoinEntriesSortTraversalZeroKnowledge.getSourceUri(term)) .filter(uri => sources.includes(uri)) .length; } /** * Determine a score for the selectivity of the given pattern. * The fewer variables, the higher the score. * @param pattern A quad pattern. */ static getScoreSelectivity(pattern) { const terms = pattern.type === 'pattern' ? (0, rdf_terms_1.getTerms)(pattern) : [pattern.subject, pattern.object, pattern.graph]; return rdf_terms_1.QUAD_TERM_NAMES.length - (0, rdf_terms_1.getVariables)(terms).length; } /** * This sorts join entries by first prioritizing triple patterns in BGPs, and then all other operation types. * * Sort the patterns in BGPs by the following priorities: * 1. A source in S or O (not O if rdf:type) (seed rule, no vocab rule) * 2. Most selective: fewest variables (filtering rule, dependency-respecting rule) * @param entries Quad patterns. * @param sources The sources that are currently being queried. */ static sortJoinEntries(entries, sources) { return [...entries].sort((entryA, entryB) => { if (((0, utils_1.isKnownOperation)(entryA.operation, utils_algebra_1.Algebra.Types.PATTERN) || (0, utils_1.isKnownOperation)(entryA.operation, utils_algebra_1.Algebra.Types.PATH)) && ((0, utils_1.isKnownOperation)(entryB.operation, utils_algebra_1.Algebra.Types.PATTERN) || (0, utils_1.isKnownOperation)(entryB.operation, utils_algebra_1.Algebra.Types.PATH))) { const compSeedNonVocab = ActorRdfJoinEntriesSortTraversalZeroKnowledge .getScoreSeedNonVocab(entryB.operation, sources) - ActorRdfJoinEntriesSortTraversalZeroKnowledge.getScoreSeedNonVocab(entryA.operation, sources); if (compSeedNonVocab === 0) { return ActorRdfJoinEntriesSortTraversalZeroKnowledge.getScoreSelectivity(entryB.operation) - ActorRdfJoinEntriesSortTraversalZeroKnowledge.getScoreSelectivity(entryA.operation); } return compSeedNonVocab; } return entryA.operation.type === utils_algebra_1.Algebra.Types.PATTERN ? -1 : 1; }); } async test(_action) { return (0, core_1.passTest)({ accuracy: 1 }); } async run(action) { // Determine all current sources const sources = []; const dataSources = action.context .get(context_entries_1.KeysQueryOperation.querySources); if (dataSources) { for (const source of dataSources) { const sourceValue = source.source.referenceValue; if (typeof sourceValue === 'string') { sources.push(sourceValue); } } } return { entries: ActorRdfJoinEntriesSortTraversalZeroKnowledge.sortJoinEntries(action.entries, sources) }; } } exports.ActorRdfJoinEntriesSortTraversalZeroKnowledge = ActorRdfJoinEntriesSortTraversalZeroKnowledge; //# sourceMappingURL=ActorRdfJoinEntriesSortTraversalZeroKnowledge.js.map