UNPKG

unrdf

Version:

Production-ready RDF knowledge graph library with Knowledge Hooks, SPARC methodology, and Knowledge Substrate optimization

220 lines (218 loc) 7.19 kB
import { Store } from "n3"; import { QueryEngine } from "@comunica/query-sparql"; //#region src/knowledge-engine/query.mjs function createQueryEngine() { return new QueryEngine(); } /** * Run a SPARQL query against a store. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL query string * @param {Object} [options] - Query options * @param {number} [options.limit] - Maximum number of results * @param {AbortSignal} [options.signal] - Abort signal for cancellation * @param {boolean} [options.deterministic] - Enable deterministic results * @returns {Promise<any>} Promise resolving to the query result * * @throws {Error} If query execution fails * * @example * const store = new Store(); * // ... add quads to store * * const results = await query(store, ` * SELECT ?s ?o WHERE { * ?s <http://example.org/knows> ?o * } * `); * console.log(results); // Array of binding objects */ async function query(store, sparql, options = {}) { if (!store || typeof store.getQuads !== "function") throw new TypeError("query: store must be a valid Store instance"); if (typeof sparql !== "string" || !sparql.trim()) throw new TypeError("query: sparql must be a non-empty string"); try { const queryOptions = { sources: [store], ...options }; const comunica = createQueryEngine(); const res = await comunica.query(sparql, queryOptions); switch (res.resultType) { case "bindings": { const executed = await res.execute(); const rows = []; for await (const binding of executed) rows.push(Object.fromEntries([...binding].map(([k, v]) => [k.value, v.value]))); return rows; } case "boolean": return res.booleanResult ?? await res.execute(); case "quads": { const executed = await res.execute(); const quads = []; for await (const quad of executed) quads.push(quad); return new Store(quads); } default: throw new Error(`Unsupported query type: ${res.resultType}`); } } catch (error) { throw new Error(`SPARQL query failed: ${error.message}`); } } /** * Execute a SELECT query and return bindings. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL SELECT query * @param {Object} [options] - Query options * @returns {Promise<Array<Object>>} Promise resolving to array of binding objects * * @throws {Error} If query execution fails * * @example * const bindings = await select(store, ` * SELECT ?name ?age WHERE { * ?person <http://example.org/name> ?name ; * <http://example.org/age> ?age . * } * `); */ async function select(store, sparql, options = {}) { const result = await query(store, sparql, options); if (Array.isArray(result)) return result; throw new Error("SELECT query did not return bindings"); } /** * Execute an ASK query and return boolean result. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL ASK query * @param {Object} [options] - Query options * @returns {Promise<boolean>} Promise resolving to boolean result * * @throws {Error} If query execution fails * * @example * const hasData = await ask(store, ` * ASK WHERE { * ?s ?p ?o . * } * `); */ async function ask(store, sparql, options = {}) { const result = await query(store, sparql, options); if (typeof result === "boolean") return result; throw new Error("ASK query did not return boolean result"); } /** * Execute a CONSTRUCT query and return a new store. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL CONSTRUCT query * @param {Object} [options] - Query options * @returns {Promise<Store>} Promise resolving to a new store with constructed quads * * @throws {Error} If query execution fails * * @example * const constructed = await construct(store, ` * CONSTRUCT { * ?person <http://example.org/type> <http://example.org/Person> . * } WHERE { * ?person <http://example.org/name> ?name . * } * `); */ async function construct(store, sparql, options = {}) { const result = await query(store, sparql, options); if (result && typeof result.getQuads === "function") return result; throw new Error("CONSTRUCT query did not return a store"); } /** * Execute a DESCRIBE query and return a new store. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL DESCRIBE query * @param {Object} [options] - Query options * @returns {Promise<Store>} Promise resolving to a new store with described quads * * @throws {Error} If query execution fails * * @example * const described = await describe(store, ` * DESCRIBE <http://example.org/alice> * `); */ async function describe(store, sparql, options = {}) { const result = await query(store, sparql, options); if (result && typeof result.getQuads === "function") return result; throw new Error("DESCRIBE query did not return a store"); } /** * Execute a SPARQL UPDATE operation (INSERT, DELETE, etc.). * @param {Store} store - The store to update * @param {string} sparql - The SPARQL UPDATE query * @param {Object} [options] - Update options * @returns {Promise<Store>} Promise resolving to the updated store * * @throws {Error} If update execution fails * * @example * const updated = await update(store, ` * INSERT DATA { * <http://example.org/alice> <http://example.org/age> "30" . * } * `); */ async function update(store, sparql, options = {}) { if (!store || typeof store.getQuads !== "function") throw new TypeError("update: store must be a valid Store instance"); if (typeof sparql !== "string" || !sparql.trim()) throw new TypeError("update: sparql must be a non-empty string"); try { const source = { type: "rdfjsSource", value: store }; const updateOptions = { sources: [source], ...options }; const comunica = createQueryEngine(); await comunica.query(sparql, updateOptions); return store; } catch (error) { throw new Error(`SPARQL update failed: ${error.message}`); } } /** * Get query execution statistics. * @param {Store} store - The store to query against * @param {string} sparql - The SPARQL query * @param {Object} [options] - Query options * @returns {Promise<Object>} Promise resolving to execution statistics * * @example * const stats = await getQueryStats(store, sparql); * console.log(`Execution time: ${stats.duration}ms`); * console.log(`Result count: ${stats.resultCount}`); */ async function getQueryStats(store, sparql, options = {}) { const startTime = Date.now(); try { const result = await query(store, sparql, options); const endTime = Date.now(); let resultCount = 0; if (Array.isArray(result)) resultCount = result.length; else if (result && typeof result.getQuads === "function") resultCount = result.size; else if (typeof result === "boolean") resultCount = 1; return { duration: endTime - startTime, resultCount, success: true }; } catch (error) { const endTime = Date.now(); return { duration: endTime - startTime, resultCount: 0, success: false, error: error.message }; } } //#endregion export { ask, construct, describe, getQueryStats, query, select, update }; //# sourceMappingURL=query-BDTu1b1k.mjs.map