diff --git a/src/edge_manager.ts b/src/edge_manager.ts index 543a6ea5..a5815bfe 100644 --- a/src/edge_manager.ts +++ b/src/edge_manager.ts @@ -14,6 +14,8 @@ import { UnavailableAPITracker } from './types'; import { RecordsByQEdgeID } from './results_assembly/query_results'; import path from 'path'; import { promises as fs } from 'fs'; +import KnowledgeGraph from './graph/knowledge_graph'; +import BTEGraph from './graph/graph'; export default class QueryEdgeManager { private _qEdges: QEdge[]; @@ -211,7 +213,7 @@ export default class QueryEdgeManager { subjectIDs.some((curie) => execSubjectCuries.includes(curie)) || execSubjectCuries.length === 0; const objectMatch = objectIDs.some((curie) => execObjectCuries.includes(curie)) || execObjectCuries.length === 0; - //if both ends match then keep record + // if both ends match then keep record // Don't keep self-edges const selfEdge = [...subjectIDs].some((curie) => objectIDs.includes(curie)); @@ -230,6 +232,32 @@ export default class QueryEdgeManager { return keep; } + _constrainEdgeRecords(qEdge: QEdge, records: Record[]) { + const keep: Record[] = []; + const bte = new BTEGraph(); + const kg = new KnowledgeGraph(); + bte.update(records); + kg.update(bte); + records.forEach(record => { + const edge = kg.kg.edges[record.recordHash]; + const sub = qEdge.reverse ? kg.kg.nodes[edge.object] : kg.kg.nodes[edge.subject]; + const obj = qEdge.reverse ? kg.kg.nodes[edge.subject] : kg.kg.nodes[edge.object]; + if (qEdge.meetsConstraints(edge, sub, obj)) { + keep.push(record); + } + }); + + debug(`'${qEdge.getID()}' dropped (${records.length - keep.length}) records based on edge/node constraints.`); + this.logs.push( + new LogEntry( + 'DEBUG', + null, + `'${qEdge.getID()}' kept (${keep.length}) / dropped (${records.length - keep.length}) records (based on node/edge constraints).`, + ).getLog(), + ); + return keep; + } + collectRecords(): boolean { //go through edges and collect records organized by edge let recordsByQEdgeID: RecordsByQEdgeID = {}; @@ -296,8 +324,10 @@ export default class QueryEdgeManager { updateEdgeRecords(currentQEdge: QEdge): void { //1. filter edge records based on current status - const filteredRecords = this._filterEdgeRecords(currentQEdge); - //2.trigger node update / entity update based on new status + let filteredRecords = this._filterEdgeRecords(currentQEdge); + //2. make sure node/edge constraints are met + filteredRecords = this._constrainEdgeRecords(currentQEdge, filteredRecords); + //3. trigger node update / entity update based on new status currentQEdge.storeRecords(filteredRecords); } diff --git a/src/index.ts b/src/index.ts index 4edf5677..06431863 100644 --- a/src/index.ts +++ b/src/index.ts @@ -724,8 +724,6 @@ export default class TRAPIQueryHandler { //update query results await this.trapiResultsAssembler.update( manager.getOrganizedRecords(), - this.queryGraphHandler, - this.knowledgeGraph.kg, !(this.options.smartAPIID || this.options.teamName) ); this.logs = [...this.logs, ...this.trapiResultsAssembler.logs]; diff --git a/src/query_edge.ts b/src/query_edge.ts index 331b893f..c6416e76 100644 --- a/src/query_edge.ts +++ b/src/query_edge.ts @@ -356,7 +356,6 @@ export default class QEdge { storeRecords(records: Record[]): void { - debug((new Error()).stack) debug(`(6) Storing records...`); // store new records in current edge this.records = records; diff --git a/src/results_assembly/query_results.ts b/src/results_assembly/query_results.ts index 048baf6a..5d1f95f9 100644 --- a/src/results_assembly/query_results.ts +++ b/src/results_assembly/query_results.ts @@ -151,8 +151,6 @@ export default class TrapiResultsAssembler { _getQueryGraphSolutions( recordsByQEdgeID: RecordsByQEdgeID, qEdgeID: string, - queryGraph: QueryGraph, - kg: TrapiKnowledgeGraph, edgeCount: number, queryGraphSolutions: QueryGraphSolutionEdge[][], queryGraphSolution: QueryGraphSolutionEdge[], @@ -192,7 +190,7 @@ export default class TrapiResultsAssembler { records .filter((record) => { - return [getMatchingPrimaryCurie(record), undefined].indexOf(primaryCurieToMatch) > -1 && queryGraph.edges[qEdgeID].meetsConstraints(kg.edges[record.recordHash], kg.nodes[kg.edges[record.recordHash].subject], kg.nodes[kg.edges[record.recordHash].object]); + return [getMatchingPrimaryCurie(record), undefined].indexOf(primaryCurieToMatch) > -1; }) .forEach((record, i) => { // primaryCurie example: 'NCBIGene:1234' @@ -225,8 +223,6 @@ export default class TrapiResultsAssembler { this._getQueryGraphSolutions( recordsByQEdgeID, connectedQEdgeID, - queryGraph, - kg, edgeCount, queryGraphSolutions, queryGraphSolution, @@ -277,7 +273,7 @@ export default class TrapiResultsAssembler { * can safely assume every call to update contains all the records. * */ - async update(recordsByQEdgeID: RecordsByQEdgeID, queryGraph: QueryGraph, kg: TrapiKnowledgeGraph, shouldScore = true): Promise { + async update(recordsByQEdgeID: RecordsByQEdgeID, shouldScore = true): Promise { debug(`Updating query results now!`); let scoreCombos: ScoreCombos; @@ -322,8 +318,6 @@ export default class TrapiResultsAssembler { this._getQueryGraphSolutions( recordsByQEdgeID, initialQEdgeID, - queryGraph, - kg, qEdgeCount, queryGraphSolutions, [], // first queryGraphSolution