From e70c4dedf53c7d8538c7f1cc67a911aba5852e35 Mon Sep 17 00:00:00 2001 From: sahalali Date: Mon, 15 Jul 2024 16:33:15 +0530 Subject: [PATCH] Added support to filter by property --- src/constant/recon-queries.constants.ts | 4 ++- src/dto/recon.dto.ts | 7 ++++- src/enum/reconciliation-types.enum.ts | 11 ++++++++ src/service/artsdata/artsdata.service.ts | 33 +++++++++++++++++++----- src/service/recon/recon.service.ts | 15 ++++++++--- 5 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/constant/recon-queries.constants.ts b/src/constant/recon-queries.constants.ts index 00353c9..cb3ae7f 100644 --- a/src/constant/recon-queries.constants.ts +++ b/src/constant/recon-queries.constants.ts @@ -24,10 +24,12 @@ WHERE { values ?query { "QUERY_PLACE_HOLDER" } TYPE_PLACE_HOLDER - + ?search a luc-index:INDEX_PLACE_HOLDER ; luc:query ?query ; luc:entities ?entity . + PROPERTY_PLACE_HOLDER + FILTER (CONTAINS(STR(?entity),"kg.artsdata.ca/resource/")) ?entity luc:score ?score; diff --git a/src/dto/recon.dto.ts b/src/dto/recon.dto.ts index 636fc63..a4338c9 100644 --- a/src/dto/recon.dto.ts +++ b/src/dto/recon.dto.ts @@ -1,4 +1,5 @@ import { ApiProperty } from "@nestjs/swagger"; +import { MatchQualifierEnum, MatchQuantifierEnum } from "../enum"; class ReconciliationType { @ApiProperty() @@ -45,11 +46,15 @@ export class ReconciliationResponse { } -class QueryCondition { +export class QueryCondition { @ApiProperty() matchType: string; @ApiProperty() v: string; + @ApiProperty() + pid?: string; + @ApiProperty() + required?: boolean; } class ReconciliationQuery { diff --git a/src/enum/reconciliation-types.enum.ts b/src/enum/reconciliation-types.enum.ts index 6eccdc4..51518f4 100644 --- a/src/enum/reconciliation-types.enum.ts +++ b/src/enum/reconciliation-types.enum.ts @@ -15,4 +15,15 @@ export enum LanguageTagEnum { export enum ReconRequestMatchTypeEnum { NAME = "name", PROPERTY = "property" +} + +export enum MatchQuantifierEnum { + // ANY = "any", + ALL = "all", + NONE = "none" +} + +export enum MatchQualifierEnum { + WILDCARD_MATCH = "WildcardMatch", + } \ No newline at end of file diff --git a/src/service/artsdata/artsdata.service.ts b/src/service/artsdata/artsdata.service.ts index 845a9a4..b43b9be 100644 --- a/src/service/artsdata/artsdata.service.ts +++ b/src/service/artsdata/artsdata.service.ts @@ -3,6 +3,7 @@ import { ARTSDATA } from "../../config"; import { QUERIES } from "../../constant/recon-queries.constants"; import { HttpService } from "../http"; import { ReconciliationServiceHelper } from "../../helper/reconciliation-service.helper"; +import { QueryCondition } from "../../dto"; @Injectable() export class ArtsdataService { @@ -16,12 +17,22 @@ export class ArtsdataService { return sparqlEndpoint.toString(); } - async getReconciliationResult(name: string, type: string, limit?: number) { + async getReconciliationResult(name: string, propertyConditions: QueryCondition[], type: string, limit?: number) { if (name === undefined || name === null || name === "") { return []; } - const graphdbIndex: string = ReconciliationServiceHelper.getGraphdbIndex(type); + + const rawSparqlQuery: string = this._getSparqlQuery(name, type, limit); + const rawSparqlQueryWithPropertyFilters = this._resolvePropertyConditions(rawSparqlQuery, propertyConditions); + const sparqlQuery: string = "query=" + encodeURIComponent(rawSparqlQueryWithPropertyFilters); const sparqlEndpoint: string = this._getArtsdataEndPoint(); + const response = await this.httpService.postRequest(sparqlEndpoint, sparqlQuery); + return ReconciliationServiceHelper.formatReconciliationResponse(name, response); + } + + + private _getSparqlQuery(name: string, type: string, limit: number | undefined): string { + const graphdbIndex: string = ReconciliationServiceHelper.getGraphdbIndex(type); let rawSparqlQuery: string = QUERIES.RECONCILITAION_QUERY .replace("INDEX_PLACE_HOLDER", graphdbIndex) .replace("QUERY_PLACE_HOLDER", name); @@ -33,14 +44,22 @@ export class ArtsdataService { } rawSparqlQuery = rawSparqlQuery.replace("TYPE_PLACE_HOLDER", typePlaceholderReplace); - if (limit && limit > 0) { rawSparqlQuery = rawSparqlQuery + " LIMIT " + limit; } - const sparqlQuery = "query=" + encodeURIComponent(rawSparqlQuery); - const response = await this.httpService.postRequest(sparqlEndpoint, sparqlQuery); - return ReconciliationServiceHelper.formatReconciliationResponse(name, response); + return rawSparqlQuery; } - + private _resolvePropertyConditions(rawSparqlQuery: string, propertyConditions: QueryCondition[]) { + const propertyTriples: string = ""; + propertyConditions.forEach((condition) => { + if (condition.required) { + propertyTriples.concat(`?entity schema:${condition.pid} ${condition.v} .`); + } else { + propertyTriples.concat(`OPTIONAL {?entity schema:${condition.pid} ${condition.v} .}`); + } + }); + rawSparqlQuery = rawSparqlQuery.replace("PROPERTY_PLACE_HOLDER", propertyTriples); + return rawSparqlQuery; + } } diff --git a/src/service/recon/recon.service.ts b/src/service/recon/recon.service.ts index 4d7b084..c8b188f 100644 --- a/src/service/recon/recon.service.ts +++ b/src/service/recon/recon.service.ts @@ -1,7 +1,7 @@ import { Injectable } from "@nestjs/common"; import { ArtsdataService } from "../artsdata"; import { ManifestService } from "../manifest"; -import { ReconciliationRequest, ReconciliationResponse, ReconciliationResults } from "../../dto"; +import { QueryCondition, ReconciliationRequest, ReconciliationResponse, ReconciliationResults } from "../../dto"; import { Exception } from "../../helper"; import { ReconRequestMatchTypeEnum } from "../../enum"; @@ -35,12 +35,19 @@ export class ReconciliationService { } for (const reconciliationQuery of queries) { const { type, limit, conditions } = reconciliationQuery; - const query = conditions - .find(condition => condition.matchType == ReconRequestMatchTypeEnum.NAME)?.v; - const candidates = await this._artsdataService.getReconciliationResult(query as string, type, limit); + + const { name, propertyConditions } = this._resolveConditions(conditions); + const candidates = await this._artsdataService.getReconciliationResult(name as string, propertyConditions, type, limit); results.push({ candidates: candidates }); } return { results }; } + private _resolveConditions(conditions: QueryCondition[]) { + const name = conditions + .find(condition => condition.matchType == ReconRequestMatchTypeEnum.NAME)?.v; + const propertyConditions = conditions + .filter(condition => condition.matchType == ReconRequestMatchTypeEnum.PROPERTY); + return { name, propertyConditions }; + } }