@comake/skl-js-engine
Version:
Standard Knowledge Language Javascript Engine
204 lines • 9.95 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.SparqlQueryAdapter = void 0;
const SparqlUtil_1 = require("../../../util/SparqlUtil");
const TripleUtil_1 = require("../../../util/TripleUtil");
const InMemorySparqlQueryExecutor_1 = require("./query-executor/InMemorySparqlQueryExecutor");
const SparqlEndpointQueryExecutor_1 = require("./query-executor/SparqlEndpointQueryExecutor");
const SparqlQueryBuilder_1 = require("./SparqlQueryBuilder");
const SparqlUpdateBuilder_1 = require("./SparqlUpdateBuilder");
/**
* A {@link QueryAdapter} that stores data in a database through a sparql endpoint.
*/
class SparqlQueryAdapter {
constructor(options) {
this.setTimestamps = options.setTimestamps ?? false;
switch (options.type) {
case 'memory':
this.queryExecutor = new InMemorySparqlQueryExecutor_1.InMemorySparqlQueryExecutor();
break;
case 'sparql':
this.queryExecutor = new SparqlEndpointQueryExecutor_1.SparqlEndpointQueryExecutor(options);
break;
default:
throw new Error('No schema source found in setSchema args.');
}
}
async executeRawQuery(query) {
const response = await this.queryExecutor.executeSparqlSelectAndGetDataRaw(query);
if (response.length === 0) {
return [];
}
return (0, SparqlUtil_1.selectQueryResultsAsJSValues)(response);
}
async executeRawConstructQuery(query, frame) {
const response = await this.queryExecutor.executeSparqlConstructAndGetDataRaw(query);
if (response.length === 0) {
return { '@graph': [] };
}
return await (0, TripleUtil_1.triplesToJsonldWithFrame)(response, frame);
}
async executeRawUpdate(query) {
await this.queryExecutor.executeRawSparqlUpdate(query);
}
async find(options) {
const jsonld = await this.findAllAsJsonLd({ ...options, limit: 1 });
if (Array.isArray(jsonld) && !options?.skipFraming) {
if (jsonld.length === 0) {
return null;
}
if (jsonld.length === 1) {
return jsonld[0];
}
}
return jsonld;
}
async findBy(where) {
return this.find({ where });
}
async findAll(options) {
const jsonld = await this.findAllAsJsonLd(options);
if (Array.isArray(jsonld)) {
return jsonld;
}
return [jsonld];
}
async findAllAsJsonLd(options) {
const queryBuilder = new SparqlQueryBuilder_1.SparqlQueryBuilder();
const { where, selectionTriples, entityOrder } = await this.buildFindAllQueryData(queryBuilder, options);
if (entityOrder && entityOrder.length === 0) {
return [];
}
const queryData = queryBuilder.buildEntitySelectPatternsFromOptions(SparqlUtil_1.entityVariable, options);
const query = queryBuilder.buildConstructFromEntitySelectQuery(where, selectionTriples, options?.select, queryData.selectVariables);
return await this.executeEntitySelectQuery(query, options, entityOrder);
}
async buildFindAllQueryData(queryBuilder, options) {
const queryData = queryBuilder.buildEntitySelectPatternsFromOptions(SparqlUtil_1.entityVariable, options);
const entitySelectQuery = queryData.where.length > 0
? (0, SparqlUtil_1.createSparqlSelectQuery)([
options?.entitySelectVariable ?? SparqlUtil_1.entityVariable,
...(queryData.selectVariables?.map(({ variable, expression }) => ({
variable,
expression,
})) ?? []),
], queryData.where, queryData.orders, queryData.group ?? options?.group, options?.limit, options?.offset)
: undefined;
let entityOrder;
if (queryData.orders.length > 0 && options?.limit !== 1 && entitySelectQuery) {
const entitySelectResponse = await this.queryExecutor.executeSparqlSelectAndGetData(entitySelectQuery);
const valuesByVariable = (0, SparqlUtil_1.groupSelectQueryResultsByKey)(entitySelectResponse);
entityOrder = (0, SparqlUtil_1.getEntityVariableValuesFromVariables)(valuesByVariable);
if (entityOrder.length === 0) {
return {
where: queryData.where,
selectionTriples: queryData.graphSelectionTriples,
entityOrder: [],
};
}
const variableValueFilters = (0, SparqlUtil_1.createValuesPatternsForVariables)(valuesByVariable);
queryData.graphWhere = [...variableValueFilters, ...queryData.graphWhere];
}
else if (entitySelectQuery) {
const entitySelectGroupQuery = (0, SparqlUtil_1.createSparqlSelectGroup)([entitySelectQuery]);
queryData.graphWhere.unshift(entitySelectGroupQuery);
}
return {
where: queryData.graphWhere,
selectionTriples: queryData.graphSelectionTriples,
entityOrder,
};
}
async executeEntitySelectQuery(query, options, entityOrder) {
const responseTriples = await this.queryExecutor.executeSparqlSelectAndGetData(query);
return await (0, TripleUtil_1.triplesToJsonld)(responseTriples, options?.skipFraming, options?.relations, options?.where, entityOrder);
}
async findAllBy(where) {
return this.findAll({ where });
}
async exists(options) {
const queryBuilder = new SparqlQueryBuilder_1.SparqlQueryBuilder();
const queryData = queryBuilder.buildEntitySelectPatternsFromOptions(SparqlUtil_1.entityVariable, options);
const values = queryData.graphWhere.filter((pattern) => pattern.type === 'values');
const query = (0, SparqlUtil_1.creteSparqlAskQuery)([...values, ...queryData.where]);
return await this.queryExecutor.executeAskQueryAndGetResponse(query);
}
async count(options) {
const queryBuilder = new SparqlQueryBuilder_1.SparqlQueryBuilder();
const queryData = queryBuilder.buildEntitySelectPatternsFromOptions(SparqlUtil_1.entityVariable, options);
const values = queryData.graphWhere.filter((pattern) => pattern.type === 'values');
const query = (0, SparqlUtil_1.createSparqlCountSelectQuery)(SparqlUtil_1.entityVariable, [...values, ...queryData.where], queryData.orders, options?.offset);
return await this.queryExecutor.executeSelectCountAndGetResponse(query);
}
async save(entityOrEntities) {
const queryBuilder = new SparqlUpdateBuilder_1.SparqlUpdateBuilder({ setTimestamps: this.setTimestamps });
const query = queryBuilder.buildUpdate(entityOrEntities);
await this.queryExecutor.executeSparqlUpdate(query);
return entityOrEntities;
}
async groupBy(options) {
const queryBuilder = new SparqlQueryBuilder_1.SparqlQueryBuilder();
const { query: selectQuery, variableMapping } = await queryBuilder.buildGroupByQuery(options);
const results = await this.queryExecutor.executeSparqlSelectAndGetData(selectQuery);
// Create reverse mapping from path to variable name
const reverseMapping = Object.entries(variableMapping).reduce((acc, [varName, path]) => {
acc[path] = varName;
return acc;
}, {});
// Transform results
const groupResults = results.map((result) => {
const group = {};
options.groupBy?.forEach((path) => {
const varName = reverseMapping[path];
if (!varName) {
throw new Error(`No variable mapping found for path: ${path}`);
}
const value = result[varName].value;
// Try to convert to number if possible
group[path] = isNaN(Number(value)) ? value : Number(value);
});
if (options.dateGrouping) {
const dateGroupVarName = reverseMapping['dateGroup'];
group.dateGroup = result[dateGroupVarName].value;
}
const countVarName = reverseMapping['count'];
const entityIdsVarName = reverseMapping['entityIds'];
return {
group,
count: parseInt(result[countVarName].value, 10),
entityIds: result[entityIdsVarName].value.split(" "),
};
});
return {
results: groupResults,
meta: {
totalCount: groupResults.reduce((sum, curr) => sum + curr.count, 0),
dateRange: options.dateRange,
groupings: options.groupBy || [],
},
};
}
async update(idOrIds, attributes) {
const queryBuilder = new SparqlUpdateBuilder_1.SparqlUpdateBuilder({ setTimestamps: this.setTimestamps });
const query = queryBuilder.buildPartialUpdate(idOrIds, attributes);
await this.queryExecutor.executeSparqlUpdate(query);
}
async delete(idOrIds) {
const queryBuilder = new SparqlUpdateBuilder_1.SparqlUpdateBuilder();
const query = queryBuilder.buildDeleteById(idOrIds);
await this.queryExecutor.executeSparqlUpdate(query);
}
async destroy(entityOrEntities) {
const queryBuilder = new SparqlUpdateBuilder_1.SparqlUpdateBuilder();
const query = queryBuilder.buildDelete(entityOrEntities);
await this.queryExecutor.executeSparqlUpdate(query);
return entityOrEntities;
}
async destroyAll() {
const queryBuilder = new SparqlUpdateBuilder_1.SparqlUpdateBuilder();
const query = queryBuilder.buildDeleteAll();
await this.queryExecutor.executeSparqlUpdate(query);
}
}
exports.SparqlQueryAdapter = SparqlQueryAdapter;
//# sourceMappingURL=SparqlQueryAdapter.js.map