From b3235a186d1b46930796e60f2c1ed020d79bc7c1 Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Mon, 22 Mar 2021 20:14:01 -0700 Subject: [PATCH 1/6] chore(release): 1.0.0 --- CHANGELOG.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90e4b782..45d7a67e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [1.0.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.7.0...v1.0.0) (2021-03-23) + + +### Features + +* :sparkles: support query graph with explain type of query ([2d767fd](https://github.com/kevinxin90/bte_trapi_query_graph_handler/commit/2d767fd67d04c8956e3d55c2438def12b79ec104)) + ## [0.7.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.6.0...v0.7.0) (2021-03-18) diff --git a/package-lock.json b/package-lock.json index bb34c56c..18e02325 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.7.0", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c1d53fd8..82d4419b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.7.0", + "version": "1.0.0", "description": "A nodejs module to query TRAPI Query Graph", "main": "built/index.js", "scripts": { From e3929aa61e12b98929442cc8ca718bf136af203b Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Tue, 23 Mar 2021 07:30:40 -0700 Subject: [PATCH 2/6] style: :art: style code --- src/graph/graph.js | 172 +++++++++++++++--------------- src/graph/kg_edge.js | 89 ++++++++-------- src/graph/kg_node.js | 53 +++++----- src/graph/knowledge_graph.js | 200 +++++++++++++++++------------------ src/index.js | 2 +- src/qedge2bteedge.js | 6 +- src/query_execution_edge.js | 128 +++++++++++----------- src/query_graph.js | 24 +++-- src/update_nodes.js | 7 +- 9 files changed, 342 insertions(+), 339 deletions(-) diff --git a/src/graph/graph.js b/src/graph/graph.js index e862dff7..846ad065 100644 --- a/src/graph/graph.js +++ b/src/graph/graph.js @@ -1,95 +1,95 @@ -const kg_edge = require("./kg_edge"); -const kg_node = require("./kg_node"); -const helper = require("../helper"); +const kg_edge = require('./kg_edge'); +const kg_node = require('./kg_node'); +const helper = require('../helper'); module.exports = class Graph { - constructor() { - this.nodes = {}; - this.edges = {}; - this.paths = {}; - this.helper = new helper(); - this.subscribers = []; - } + constructor() { + this.nodes = {}; + this.edges = {}; + this.paths = {}; + this.helper = new helper(); + this.subscribers = []; + } - update(queryResult) { - const bteAttributes = ['name', 'label', 'id', 'api', 'provided_by', 'publications']; - queryResult.map((record) => { - const inputPrimaryID = this.helper._getInputID(record); - const inputQGID = this.helper._getInputQueryNodeID(record); - const inputID = inputPrimaryID + '-' + inputQGID; - const outputPrimaryID = this.helper._getOutputID(record); - const outputQGID = this.helper._getOutputQueryNodeID(record); - const outputID = outputPrimaryID + '-' + outputQGID; - const edgeID = this.helper._getKGEdgeID(record); - if (!(outputID in this.nodes)) { - this.nodes[outputID] = new kg_node(outputID, { - primaryID: outputPrimaryID, - qgID: outputQGID, - equivalentIDs: this.helper._getOutputEquivalentIds(record), - label: this.helper._getOutputLabel(record), - category: this.helper._getOutputCategory(record), - nodeAttributes: this.helper._getOutputAttributes(record) - }) - } - if (!(inputID in this.nodes)) { - this.nodes[inputID] = new kg_node(inputID, { - primaryID: inputPrimaryID, - qgID: inputQGID, - equivalentIDs: this.helper._getInputEquivalentIds(record), - label: this.helper._getInputLabel(record), - category: this.helper._getInputCategory(record), - nodeAttributes: this.helper._getInputAttributes(record) - }) - } - this.nodes[outputID].addSourceNode(inputID); - this.nodes[outputID].addSourceQGNode(inputQGID); - this.nodes[inputID].addTargetNode(outputID); - this.nodes[inputID].addTargetQGNode(outputQGID); - if (!(edgeID in this.edges)) { - this.edges[edgeID] = new kg_edge(edgeID, { - predicate: this.helper._getPredicate(record), - subject: inputPrimaryID, - object: outputPrimaryID - }) - } - this.edges[edgeID].addAPI(this.helper._getAPI(record)); - this.edges[edgeID].addSource(this.helper._getSource(record)); - this.edges[edgeID].addPublication(this.helper._getPublication(record)); - Object.keys(record) - .filter((k) => !(bteAttributes.includes(k) || k.startsWith('$'))) - .map((item) => { - this.edges[edgeID].addAdditionalAttributes(item, record[item]); - }); - }) - } + update(queryResult) { + const bteAttributes = ['name', 'label', 'id', 'api', 'provided_by', 'publications']; + queryResult.map((record) => { + const inputPrimaryID = this.helper._getInputID(record); + const inputQGID = this.helper._getInputQueryNodeID(record); + const inputID = inputPrimaryID + '-' + inputQGID; + const outputPrimaryID = this.helper._getOutputID(record); + const outputQGID = this.helper._getOutputQueryNodeID(record); + const outputID = outputPrimaryID + '-' + outputQGID; + const edgeID = this.helper._getKGEdgeID(record); + if (!(outputID in this.nodes)) { + this.nodes[outputID] = new kg_node(outputID, { + primaryID: outputPrimaryID, + qgID: outputQGID, + equivalentIDs: this.helper._getOutputEquivalentIds(record), + label: this.helper._getOutputLabel(record), + category: this.helper._getOutputCategory(record), + nodeAttributes: this.helper._getOutputAttributes(record), + }); + } + if (!(inputID in this.nodes)) { + this.nodes[inputID] = new kg_node(inputID, { + primaryID: inputPrimaryID, + qgID: inputQGID, + equivalentIDs: this.helper._getInputEquivalentIds(record), + label: this.helper._getInputLabel(record), + category: this.helper._getInputCategory(record), + nodeAttributes: this.helper._getInputAttributes(record), + }); + } + this.nodes[outputID].addSourceNode(inputID); + this.nodes[outputID].addSourceQGNode(inputQGID); + this.nodes[inputID].addTargetNode(outputID); + this.nodes[inputID].addTargetQGNode(outputQGID); + if (!(edgeID in this.edges)) { + this.edges[edgeID] = new kg_edge(edgeID, { + predicate: this.helper._getPredicate(record), + subject: inputPrimaryID, + object: outputPrimaryID, + }); + } + this.edges[edgeID].addAPI(this.helper._getAPI(record)); + this.edges[edgeID].addSource(this.helper._getSource(record)); + this.edges[edgeID].addPublication(this.helper._getPublication(record)); + Object.keys(record) + .filter((k) => !(bteAttributes.includes(k) || k.startsWith('$'))) + .map((item) => { + this.edges[edgeID].addAdditionalAttributes(item, record[item]); + }); + }); + } - /** + /** * Register subscribers * @param {object} subscriber */ - subscribe(subscriber) { - this.subscribers.push(subscriber); - } + subscribe(subscriber) { + this.subscribers.push(subscriber); + } - /** - * Unsubscribe a listener - * @param {object} subscriber - */ - unsubscribe(subscriber) { - this.subscribers = this.subscribers.filter((fn) => { - if (fn != subscriber) return fn; - }); - } + /** + * Unsubscribe a listener + * @param {object} subscriber + */ + unsubscribe(subscriber) { + this.subscribers = this.subscribers.filter((fn) => { + if (fn != subscriber) return fn; + }); + } - /** - * Nofity all listeners - */ - notify() { - this.subscribers.map((subscriber) => { - subscriber.update({ - nodes: this.nodes, - edges: this.edges - }); - }); - } -} \ No newline at end of file + /** + * Nofity all listeners + */ + notify() { + this.subscribers.map((subscriber) => { + subscriber.update({ + nodes: this.nodes, + edges: this.edges, + }); + }); + } +}; diff --git a/src/graph/kg_edge.js b/src/graph/kg_edge.js index 6882315b..3400261d 100644 --- a/src/graph/kg_edge.js +++ b/src/graph/kg_edge.js @@ -1,53 +1,52 @@ - module.exports = class KGEdge { - constructor(id, info) { - this.id = id; - this.predicate = info.predicate; - this.subject = info.subject; - this.object = info.object; - this.apis = new Set(); - this.sources = new Set(); - this.publications = new Set(); - this.attributes = {}; - } + constructor(id, info) { + this.id = id; + this.predicate = info.predicate; + this.subject = info.subject; + this.object = info.object; + this.apis = new Set(); + this.sources = new Set(); + this.publications = new Set(); + this.attributes = {}; + } - addAPI(api) { - if (typeof api === "undefined") { - return - } - if (!Array.isArray(api)) { - api = [api]; - } - api.map(item => { - this.apis.add(item); - }) + addAPI(api) { + if (typeof api === 'undefined') { + return; } - - addSource(source) { - if (typeof source === "undefined") { - return - } - if (!Array.isArray(source)) { - source = [source]; - } - source.map(item => { - this.sources.add(item); - }) + if (!Array.isArray(api)) { + api = [api]; } + api.map((item) => { + this.apis.add(item); + }); + } - addPublication(publication) { - if (typeof publication === "undefined") { - return - } - if (!Array.isArray(publication)) { - publication = [publication]; - } - publication.map(item => { - this.publications.add(item); - }) + addSource(source) { + if (typeof source === 'undefined') { + return; } + if (!Array.isArray(source)) { + source = [source]; + } + source.map((item) => { + this.sources.add(item); + }); + } - addAdditionalAttributes(name, value) { - this.attributes[name] = value; + addPublication(publication) { + if (typeof publication === 'undefined') { + return; + } + if (!Array.isArray(publication)) { + publication = [publication]; } -} \ No newline at end of file + publication.map((item) => { + this.publications.add(item); + }); + } + + addAdditionalAttributes(name, value) { + this.attributes[name] = value; + } +}; diff --git a/src/graph/kg_node.js b/src/graph/kg_node.js index 91c5f6be..8cd9e4a5 100644 --- a/src/graph/kg_node.js +++ b/src/graph/kg_node.js @@ -1,32 +1,31 @@ - module.exports = class KGNode { - constructor(id, info) { - this.id = id; - this._primaryID = info.primaryID; - this._qgID = info.qgID; - this._curies = info.equivalentIDs; - this._semanticType = info.category; - this._nodeAttributes = info.nodeAttributes; - this._label = info.label; - this._sourceNodes = new Set(); - this._targetNodes = new Set(); - this._sourceQGNodes = new Set(); - this._targetQGNodes = new Set(); - } + constructor(id, info) { + this.id = id; + this._primaryID = info.primaryID; + this._qgID = info.qgID; + this._curies = info.equivalentIDs; + this._semanticType = info.category; + this._nodeAttributes = info.nodeAttributes; + this._label = info.label; + this._sourceNodes = new Set(); + this._targetNodes = new Set(); + this._sourceQGNodes = new Set(); + this._targetQGNodes = new Set(); + } - addSourceNode(kgNode) { - this._sourceNodes.add(kgNode); - } + addSourceNode(kgNode) { + this._sourceNodes.add(kgNode); + } - addTargetNode(kgNode) { - this._targetNodes.add(kgNode); - } + addTargetNode(kgNode) { + this._targetNodes.add(kgNode); + } - addSourceQGNode(qgNode) { - this._sourceQGNodes.add(qgNode); - } + addSourceQGNode(qgNode) { + this._sourceQGNodes.add(qgNode); + } - addTargetQGNode(qgNode) { - this._targetQGNodes.add(qgNode); - } -} \ No newline at end of file + addTargetQGNode(qgNode) { + this._targetQGNodes.add(qgNode); + } +}; diff --git a/src/graph/knowledge_graph.js b/src/graph/knowledge_graph.js index d8fdb531..d9ae7ec5 100644 --- a/src/graph/knowledge_graph.js +++ b/src/graph/knowledge_graph.js @@ -3,112 +3,112 @@ const debug = require('debug')('biothings-explorer-trapi:KnowledgeGraph'); const helper = new GraphHelper(); module.exports = class KnowledgeGraph { - constructor() { - this.nodes = {}; - this.edges = {}; - this.kg = { - nodes: this.nodes, - edges: this.edges, - }; - } + constructor() { + this.nodes = {}; + this.edges = {}; + this.kg = { + nodes: this.nodes, + edges: this.edges, + }; + } - getNodes() { - return this.nodes; - } + getNodes() { + return this.nodes; + } - getEdges() { - return this.edges; - } + getEdges() { + return this.edges; + } - _createNode(kgNode) { - const res = { - category: kgNode._semanticType, - name: kgNode._label, - attributes: [ - { - name: 'equivalent_identifiers', - value: kgNode._curies, - type: 'biolink:id', - }, - { - name: 'num_soure_nodes', - value: kgNode._sourceNodes.size, - type: 'bts:num_target_nodes' - }, - { - name: 'num_target_nodes', - value: kgNode._targetNodes.size, - type: 'bts:num_target_nodes' - }, - { - name: 'source_qg_nodes', - value: Array.from(kgNode._sourceQGNodes), - type: 'bts:source_qg_nodes' - }, - { - name: 'target_qg_nodes', - value: Array.from(kgNode._targetQGNodes), - type: 'bts:target_qg_nodes' - } - ], - }; - for (const key in kgNode._nodeAttributes) { - res.attributes.push({ - name: key, - value: kgNode._nodeAttributes[key], - type: 'bts:' + key, - }); - } - return res; + _createNode(kgNode) { + const res = { + category: kgNode._semanticType, + name: kgNode._label, + attributes: [ + { + name: 'equivalent_identifiers', + value: kgNode._curies, + type: 'biolink:id', + }, + { + name: 'num_soure_nodes', + value: kgNode._sourceNodes.size, + type: 'bts:num_target_nodes', + }, + { + name: 'num_target_nodes', + value: kgNode._targetNodes.size, + type: 'bts:num_target_nodes', + }, + { + name: 'source_qg_nodes', + value: Array.from(kgNode._sourceQGNodes), + type: 'bts:source_qg_nodes', + }, + { + name: 'target_qg_nodes', + value: Array.from(kgNode._targetQGNodes), + type: 'bts:target_qg_nodes', + }, + ], + }; + for (const key in kgNode._nodeAttributes) { + res.attributes.push({ + name: key, + value: kgNode._nodeAttributes[key], + type: 'bts:' + key, + }); } + return res; + } - _createAttributes(kgEdge) { - const attributes = [ - { - name: 'provided_by', - value: Array.from(kgEdge.sources), - type: 'biolink:provided_by', - }, - { - name: 'api', - value: Array.from(kgEdge.apis), - type: 'bts:api', - }, - { - name: 'publicatiions', - value: Array.from(kgEdge.publications), - type: 'biolink:publication', - }, - ]; - for (const key in kgEdge.attributes) { - attributes.push({ - name: key, - value: kgEdge.attributes[key], - type: 'bts:' + key, - }); - } - return attributes; + _createAttributes(kgEdge) { + const attributes = [ + { + name: 'provided_by', + value: Array.from(kgEdge.sources), + type: 'biolink:provided_by', + }, + { + name: 'api', + value: Array.from(kgEdge.apis), + type: 'bts:api', + }, + { + name: 'publicatiions', + value: Array.from(kgEdge.publications), + type: 'biolink:publication', + }, + ]; + for (const key in kgEdge.attributes) { + attributes.push({ + name: key, + value: kgEdge.attributes[key], + type: 'bts:' + key, + }); } + return attributes; + } - _createEdge(kgEdge) { - return { - predicate: kgEdge.predicate, - subject: kgEdge.subject, - object: kgEdge.object, - attributes: this._createAttributes(kgEdge), - }; - } + _createEdge(kgEdge) { + return { + predicate: kgEdge.predicate, + subject: kgEdge.subject, + object: kgEdge.object, + attributes: this._createAttributes(kgEdge), + }; + } - update(bteGraph) { - Object.keys(bteGraph.nodes).map(node => { - this.nodes[bteGraph.nodes[node]._primaryID] = this._createNode(bteGraph.nodes[node]); - }) - Object.keys(bteGraph.edges).map(edge => { - this.edges[edge] = this._createEdge(bteGraph.edges[edge]); - }) - this.kg = { - nodes: this.nodes, - edges: this.edges, - }; - } + update(bteGraph) { + Object.keys(bteGraph.nodes).map((node) => { + this.nodes[bteGraph.nodes[node]._primaryID] = this._createNode(bteGraph.nodes[node]); + }); + Object.keys(bteGraph.edges).map((edge) => { + this.edges[edge] = this._createEdge(bteGraph.edges[edge]); + }); + this.kg = { + nodes: this.nodes, + edges: this.edges, + }; + } }; diff --git a/src/index.js b/src/index.js index c44bfbfd..e53f77ea 100644 --- a/src/index.js +++ b/src/index.js @@ -9,7 +9,7 @@ const KnowledgeGraph = require('./graph/knowledge_graph'); const QueryResults = require('./query_results'); const InvalidQueryGraphError = require('./exceptions/invalid_query_graph_error'); const debug = require('debug')('biothings-explorer-trapi:main'); -const Graph = require("./graph/graph"); +const Graph = require('./graph/graph'); exports.InvalidQueryGraphError = InvalidQueryGraphError; diff --git a/src/qedge2bteedge.js b/src/qedge2bteedge.js index eb59b851..17c133ab 100644 --- a/src/qedge2bteedge.js +++ b/src/qedge2bteedge.js @@ -57,8 +57,10 @@ module.exports = class QEdge2BTEEdgeHandler { new LogEntry( 'DEBUG', null, - `BTE found ${smartapi_edges.length - } smartapi edges corresponding to ${qEdge.getID()}. These smartaip edges comes from ${new Set(this._findAPIsFromSmartAPIEdges(smartapi_edges)).size + `BTE found ${ + smartapi_edges.length + } smartapi edges corresponding to ${qEdge.getID()}. These smartaip edges comes from ${ + new Set(this._findAPIsFromSmartAPIEdges(smartapi_edges)).size } unique APIs. They are ${Array.from(new Set(this._findAPIsFromSmartAPIEdges(smartapi_edges))).join(',')}`, ).getLog(), ); diff --git a/src/query_execution_edge.js b/src/query_execution_edge.js index 4545d745..9f82e107 100644 --- a/src/query_execution_edge.js +++ b/src/query_execution_edge.js @@ -4,84 +4,84 @@ const utils = require('./utils'); const reverse = require('./biolink'); module.exports = class QExeEdge { - /** - * - * @param {string} id - QEdge ID - * @param {object} info - QEdge info, e.g. subject, object, predicate - */ - constructor(qEdge, reverse = false, prev_edge = undefined) { - this.qEdge = qEdge; - this.reverse = reverse; - this.prev_edge = prev_edge; - this.input_equivalent_identifiers = {}; - this.output_equivalent_identifiers = {}; - } + /** + * + * @param {string} id - QEdge ID + * @param {object} info - QEdge info, e.g. subject, object, predicate + */ + constructor(qEdge, reverse = false, prev_edge = undefined) { + this.qEdge = qEdge; + this.reverse = reverse; + this.prev_edge = prev_edge; + this.input_equivalent_identifiers = {}; + this.output_equivalent_identifiers = {}; + } - getID() { - return this.qEdge.getID(); - } + getID() { + return this.qEdge.getID(); + } - getHashedEdgeRepresentation() { - const toBeHashed = - this.subject.getCategories() + this.predicate + this.object.getCategories() + this.getInputCurie(); - return new helper()._generateHash(toBeHashed); - } + getHashedEdgeRepresentation() { + const toBeHashed = + this.subject.getCategories() + this.predicate + this.object.getCategories() + this.getInputCurie(); + return new helper()._generateHash(toBeHashed); + } - getPredicate() { - if (this.qEdge.predicate === undefined) { - return undefined; - } - const predicates = utils.toArray(this.qEdge.predicate); - return predicates - .map((predicate) => { - const predicateWithOutPrefix = utils.removeBioLinkPrefix(predicate); - return this.reverse === true ? reverse.reverse(predicateWithOutPrefix) : predicateWithOutPrefix; - }) - .filter((item) => !(typeof item === 'undefined')); + getPredicate() { + if (this.qEdge.predicate === undefined) { + return undefined; } + const predicates = utils.toArray(this.qEdge.predicate); + return predicates + .map((predicate) => { + const predicateWithOutPrefix = utils.removeBioLinkPrefix(predicate); + return this.reverse === true ? reverse.reverse(predicateWithOutPrefix) : predicateWithOutPrefix; + }) + .filter((item) => !(typeof item === 'undefined')); + } - getSubject() { - if (this.reverse) { - return this.qEdge.object; - } - return this.qEdge.subject; + getSubject() { + if (this.reverse) { + return this.qEdge.object; } + return this.qEdge.subject; + } - getObject() { - if (this.reverse) { - return this.qEdge.subject; - } - return this.qEdge.object; + getObject() { + if (this.reverse) { + return this.qEdge.subject; } + return this.qEdge.object; + } - isReversed() { - return this.reverse; - } + isReversed() { + return this.reverse; + } - getInputCurie() { - let curie = this.qEdge.subject.getCurie() || this.qEdge.object.getCurie(); - if (Array.isArray(curie)) { - return curie; - } - return [curie]; + getInputCurie() { + let curie = this.qEdge.subject.getCurie() || this.qEdge.object.getCurie(); + if (Array.isArray(curie)) { + return curie; } + return [curie]; + } - getInputNode() { - return this.reverse ? this.qEdge.object : this.qEdge.subject; - } + getInputNode() { + return this.reverse ? this.qEdge.object : this.qEdge.subject; + } - getOutputNode() { - return this.reverse ? this.qEdge.subject : this.qEdge.object; - } + getOutputNode() { + return this.reverse ? this.qEdge.subject : this.qEdge.object; + } - hasInputResolved() { - return !(Object.keys(this.input_equivalent_identifiers).length === 0) - } + hasInputResolved() { + return !(Object.keys(this.input_equivalent_identifiers).length === 0); + } - hasInput() { - if (this.reverse) { - return this.qEdge.object.hasInput(); - } - return this.qEdge.subject.hasInput(); + hasInput() { + if (this.reverse) { + return this.qEdge.object.hasInput(); } + return this.qEdge.subject.hasInput(); + } }; diff --git a/src/query_graph.js b/src/query_graph.js index 00e8526a..e96dda2f 100644 --- a/src/query_graph.js +++ b/src/query_graph.js @@ -1,6 +1,6 @@ const QNode = require('./query_node'); const QEdge = require('./query_edge'); -const QExecEdge = require("./query_execution_edge"); +const QExecEdge = require('./query_execution_edge'); const _ = require('lodash'); const InvalidQueryGraphError = require('./exceptions/invalid_query_graph_error'); const LogEntry = require('./log_entry'); @@ -86,16 +86,18 @@ module.exports = class QueryGraphHandler { this._validate(this.queryGraph); const paths = {}; let current_graph = this._findFirstLevelEdges(); - paths[0] = current_graph.map(item => item.edge); + paths[0] = current_graph.map((item) => item.edge); for (let i = 1; i < MAX_DEPTH + 1; i++) { current_graph = this._findNextLevelEdges(current_graph); if (current_graph.length > 0 && i === MAX_DEPTH) { - throw new InvalidQueryGraphError(`Your Query Graph exceeds the maximum query depth set in bte, which is ${MAX_DEPTH}`); + throw new InvalidQueryGraphError( + `Your Query Graph exceeds the maximum query depth set in bte, which is ${MAX_DEPTH}`, + ); } if (current_graph.length === 0) { break; } - paths[i] = current_graph.map(item => item.edge); + paths[i] = current_graph.map((item) => item.edge); } this.logs.push( new LogEntry( @@ -122,15 +124,15 @@ module.exports = class QueryGraphHandler { result.push({ current_node: objectNode, edge: new QExecEdge(this.edges[edge_id], false, undefined), - path_source_node: subjectNode + path_source_node: subjectNode, }); } if (objectNode.hasInput()) { result.push({ current_node: subjectNode, edge: new QExecEdge(this.edges[edge_id], true, undefined), - path_source_node: objectNode - }) + path_source_node: objectNode, + }); } } return result; @@ -148,14 +150,14 @@ module.exports = class QueryGraphHandler { result.push({ current_node: edge.object, edge: new QExecEdge(edge, false, grp.edge), - path_source_node: grp.path_source_node - }) + path_source_node: grp.path_source_node, + }); } else if (edge.object.getID() === grp.current_node.getID()) { result.push({ current_node: edge.subject, edge: new QExecEdge(edge, true, grp.edge), - path_source_node: grp.path_source_node - }) + path_source_node: grp.path_source_node, + }); } } } diff --git a/src/update_nodes.js b/src/update_nodes.js index 17ea9e8c..1bf0c138 100644 --- a/src/update_nodes.js +++ b/src/update_nodes.js @@ -44,9 +44,9 @@ module.exports = class NodesUpdateHandler { const curies = this._getCuries(this.qEdges); if (Object.keys(curies).length === 0) { debug(`update nodes based on previous query results!`); - qEdges.map(edge => { + qEdges.map((edge) => { edge.input_equivalent_identifiers = edge.prev_edge.output_equivalent_identifiers; - }) + }); return; } debug(`curies: ${JSON.stringify(curies)}`); @@ -88,7 +88,8 @@ module.exports = class NodesUpdateHandler { // }) queryResult.map((record) => { if (!(record.$output.obj[0].primaryID in record.$edge_metadata.trapi_qEdge_obj.output_equivalent_identifiers)) { - record.$edge_metadata.trapi_qEdge_obj.output_equivalent_identifiers[record.$output.obj[0].primaryID] = record.$output.obj; + record.$edge_metadata.trapi_qEdge_obj.output_equivalent_identifiers[record.$output.obj[0].primaryID] = + record.$output.obj; } }); } From ffb81b3f9397bd325ca38f3242f5cd110c03b288 Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Tue, 23 Mar 2021 07:41:28 -0700 Subject: [PATCH 3/6] feat: :sparkles: add chemicalsubstance node when user specify drug as output --- src/query_graph.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/query_graph.js b/src/query_graph.js index 3fda1f3f..9a54f007 100644 --- a/src/query_graph.js +++ b/src/query_graph.js @@ -40,6 +40,15 @@ module.exports = class QueryGraphHandler { this._validateNodeEdgeCorrespondence(queryGraph); } + _modify(queryGraph) { + Object.keys(queryGraph.nodes).map(nodeID => { + if (queryGraph.nodes[nodeID].category === "biolink:Drug") { + queryGraph.nodes[nodeID].category = ["biolink:Drug", "biolink:ChemicalSubstance"] + } + }) + return queryGraph; + } + /** * @private */ @@ -83,6 +92,7 @@ module.exports = class QueryGraphHandler { */ createQueryPaths() { this._validate(this.queryGraph); + this.queryGraph = this._modify(this.queryGraph); let paths = {}; let FirstLevelEdges = this._findFirstLevelEdges(); paths[0] = FirstLevelEdges.paths; From 63a3a4eefe903c0f5d8f522b1332fc47d33063c4 Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Tue, 23 Mar 2021 07:42:02 -0700 Subject: [PATCH 4/6] chore(release): 0.8.0 --- CHANGELOG.md | 7 +++++++ package-lock.json | 2 +- package.json | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90e4b782..0978f0f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [0.8.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.7.0...v0.8.0) (2021-03-23) + + +### Features + +* :sparkles: add chemicalsubstance node when user specify drug as output ([ffb81b3](https://github.com/kevinxin90/bte_trapi_query_graph_handler/commit/ffb81b3f9397bd325ca38f3242f5cd110c03b288)) + ## [0.7.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.6.0...v0.7.0) (2021-03-18) diff --git a/package-lock.json b/package-lock.json index bb34c56c..4c7b9e46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.7.0", + "version": "0.8.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c1d53fd8..286b0814 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.7.0", + "version": "0.8.0", "description": "A nodejs module to query TRAPI Query Graph", "main": "built/index.js", "scripts": { From febae208971f48a2b9ad2f7b311a3aa3240385c9 Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Tue, 23 Mar 2021 07:42:44 -0700 Subject: [PATCH 5/6] style: :art: style code --- src/query_graph.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/query_graph.js b/src/query_graph.js index 9a54f007..8914efb5 100644 --- a/src/query_graph.js +++ b/src/query_graph.js @@ -41,11 +41,11 @@ module.exports = class QueryGraphHandler { } _modify(queryGraph) { - Object.keys(queryGraph.nodes).map(nodeID => { - if (queryGraph.nodes[nodeID].category === "biolink:Drug") { - queryGraph.nodes[nodeID].category = ["biolink:Drug", "biolink:ChemicalSubstance"] + Object.keys(queryGraph.nodes).map((nodeID) => { + if (queryGraph.nodes[nodeID].category === 'biolink:Drug') { + queryGraph.nodes[nodeID].category = ['biolink:Drug', 'biolink:ChemicalSubstance']; } - }) + }); return queryGraph; } From ffd5013546f5ed3c736863cfda9f679362afa2e2 Mon Sep 17 00:00:00 2001 From: jiwen xin Date: Wed, 24 Mar 2021 15:29:59 -0700 Subject: [PATCH 6/6] chore(release): 1.0.1 --- CHANGELOG.md | 9 ++++ package-lock.json | 106 ++++++++++++---------------------------------- package.json | 14 +++--- 3 files changed, 44 insertions(+), 85 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index daebda85..b2920681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [1.0.1](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.8.0...v1.0.1) (2021-03-24) + +## [1.0.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.7.0...v1.0.0) (2021-03-23) + + +### Features + +* :sparkles: support query graph with explain type of query ([2d767fd](https://github.com/kevinxin90/bte_trapi_query_graph_handler/commit/2d767fd67d04c8956e3d55c2438def12b79ec104)) + ## [1.0.0](https://github.com/kevinxin90/bte_trapi_query_graph_handler/compare/v0.7.0...v1.0.0) (2021-03-23) ### Features diff --git a/package-lock.json b/package-lock.json index 4c7b9e46..5b2dfd02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.8.0", + "version": "1.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -449,65 +449,15 @@ } }, "@biothings-explorer/call-apis": { - "version": "1.14.0", - "resolved": "https://registry.npmjs.org/@biothings-explorer/call-apis/-/call-apis-1.14.0.tgz", - "integrity": "sha512-bSe/hCDykJGvkXJ2tV5mH2/2eB2OsuQPG9RsvOPvyT9sd0Kb4VeSuX5n4UaIKcb9QNEagsQsaQ0jqS3dYfjUxQ==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@biothings-explorer/call-apis/-/call-apis-1.15.0.tgz", + "integrity": "sha512-r92rwKNKt4EuDV9cZAT6b15Z/3ZGvbZlV0cfwDxVBZEF/VMWwjntKJVzfY+oQUdAhz7YC5wT9d1rvMy7Dp2CXQ==", "requires": { "@biothings-explorer/api-response-transform": "^1.8.0", "axios": "^0.21.1", - "biomedical_id_resolver": "^3.4.0", + "biomedical_id_resolver": "^3.4.1", "debug": "^4.3.1", "husky": "^4.3.8" - }, - "dependencies": { - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "biolink-model": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/biolink-model/-/biolink-model-0.1.2.tgz", - "integrity": "sha512-SbTcAdocPz3RfucuQc5ZmCN3HMAKRxOd3LxfeqM5yMqMpkn8jlmTWwb6o1y5Zrkh6VDHvOKqR2n1txg0Ne7uQA==", - "requires": { - "axios": "^0.21.1", - "debug": "^4.3.1", - "js-yaml": "^4.0.0", - "pascal-case": "^3.1.2" - } - }, - "biomedical_id_resolver": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/biomedical_id_resolver/-/biomedical_id_resolver-3.4.0.tgz", - "integrity": "sha512-1NMGIDTzrKplIL6nyi8NU5jpfDAo0675xEB3/HthYDj5ZH1eaALukDd56a+4ucdamtyDVA+Syaf71ONsOXzrcg==", - "requires": { - "@commitlint/cli": "^11.0.0", - "@commitlint/config-conventional": "^11.0.0", - "axios": "^0.19.2", - "biolink-model": "^0.1.2", - "debug": "^4.3.1", - "husky": "^4.3.8", - "lodash": "^4.17.21" - }, - "dependencies": { - "axios": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", - "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", - "requires": { - "follow-redirects": "1.5.10" - } - } - } - }, - "js-yaml": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.0.0.tgz", - "integrity": "sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q==", - "requires": { - "argparse": "^2.0.1" - } - } } }, "@biothings-explorer/json-transformer": { @@ -1069,9 +1019,9 @@ } }, "@types/jest": { - "version": "26.0.20", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.20.tgz", - "integrity": "sha512-9zi2Y+5USJRxd0FsahERhBwlcvFh6D2GLQnY2FH2BzK8J9s9omvNHIbvABwIluXa0fD8XVKMLTO0aOEuUfACAA==", + "version": "26.0.21", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-26.0.21.tgz", + "integrity": "sha512-ab9TyM/69yg7eew9eOwKMUmvIZAKEGZYlq/dhe5/0IMUd/QLJv5ldRMdddSn+u22N13FP3s5jYyktxuBwY0kDA==", "requires": { "jest-diff": "^26.0.0", "pretty-format": "^26.0.0" @@ -1096,9 +1046,9 @@ "integrity": "sha512-fZQQafSREFyuZcdWFAExYjBiCL7AUCdgsk80iO0q4yihYYdcIiH28CcuPTGFgLOCC8RlW49GSQxdHwZP+I7CNg==" }, "@types/node": { - "version": "14.14.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.33.tgz", - "integrity": "sha512-oJqcTrgPUF29oUP8AsUqbXGJNuPutsetaa9kTQAQce5Lx5dTYWV02ScBiT/k1BX/Z7pKeqedmvp39Wu4zR7N7g==" + "version": "14.14.35", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.35.tgz", + "integrity": "sha512-Lt+wj8NVPx0zUmUwumiVXapmaLUcAk3yPuHCFVXras9k5VT9TdhJqKqGVUQCD60OTMCl0qxJ57OiTL0Mic3Iag==" }, "@types/normalize-package-data": { "version": "2.4.0", @@ -1527,9 +1477,9 @@ } }, "biomedical_id_resolver": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/biomedical_id_resolver/-/biomedical_id_resolver-3.3.0.tgz", - "integrity": "sha512-KmbtD0GGQ434BAQZ8ANsKW3tKIgHesG27MxWxIbmEUViYvPv5b0uQkXFeGijdrv5H6wVyD7Kd+hVSdTrmBX4Vg==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/biomedical_id_resolver/-/biomedical_id_resolver-3.4.1.tgz", + "integrity": "sha512-qijulyQyV+E2nDoAAB96g+jn6mWWficmQYFiPJxYcwhYi0HFkAaH1xkz7lZdeQYBK+HdzqJOX5EvGYxyl9oLog==", "requires": { "@commitlint/cli": "^11.0.0", "@commitlint/config-conventional": "^11.0.0", @@ -6731,9 +6681,9 @@ "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=" }, "ts-jest": { - "version": "26.5.3", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.3.tgz", - "integrity": "sha512-nBiiFGNvtujdLryU7MiMQh1iPmnZ/QvOskBbD2kURiI1MwqvxlxNnaAB/z9TbslMqCsSbu5BXvSSQPc5tvHGeA==", + "version": "26.5.4", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-26.5.4.tgz", + "integrity": "sha512-I5Qsddo+VTm94SukBJ4cPimOoFZsYTeElR2xy6H2TOVs+NsvgYglW8KuQgKoApOKuaU/Ix/vrF9ebFZlb5D2Pg==", "dev": true, "requires": { "bs-logger": "0.x", @@ -6916,9 +6866,9 @@ } }, "typedoc": { - "version": "0.20.30", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.20.30.tgz", - "integrity": "sha512-A4L6JDShPFwZDt9qp7FBsEpW7C6rA5fRv6ywgBuxGxZnT2wuF5afbWzmrwqHR3Xw38V1H2L4v/VJ0S/llBwV6Q==", + "version": "0.20.33", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.20.33.tgz", + "integrity": "sha512-jzNdHmjZRQKwguhpXjIPuIjz+TpdgG2AVY8ta+qpAukv+3rBhTs4AAVd+mkonrHVYlC0EAbuAJ4urkfnn42Hwg==", "dev": true, "requires": { "colors": "^1.4.0", @@ -6930,14 +6880,14 @@ "minimatch": "^3.0.0", "progress": "^2.0.3", "shelljs": "^0.8.4", - "shiki": "^0.9.2", - "typedoc-default-themes": "^0.12.8" + "shiki": "^0.9.3", + "typedoc-default-themes": "^0.12.9" } }, "typedoc-default-themes": { - "version": "0.12.8", - "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.12.8.tgz", - "integrity": "sha512-tyjyDTKy/JLnBSwvhoqd99VIjrP33SdOtwcMD32b+OqnrjZWe8HmZECbfBoacqoxjHd58gfeNw6wA7uvqWFa4w==", + "version": "0.12.9", + "resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.12.9.tgz", + "integrity": "sha512-Jd5fYTiqzinZdoIY382W7tQXTwAzWRdg8KbHfaxmb78m1/3jL9riXtk23oBOKwhi8GFVykCOdPzEJKY87/D0LQ==", "dev": true }, "typescript": { @@ -7083,9 +7033,9 @@ } }, "vscode-textmate": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.2.0.tgz", - "integrity": "sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-5.3.1.tgz", + "integrity": "sha512-X4E7iPJzmMsL9AY4MyZrxUt0Dm/kGWreJEGdQgAHXHQrRGDdlwAu9X1LCsQ0VKUCg5wjwSS1LPpy1BOfxIw4Tw==", "dev": true }, "w3c-hr-time": { diff --git a/package.json b/package.json index 286b0814..0d38476f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@biothings-explorer/query_graph_handler", - "version": "0.8.0", + "version": "1.0.1", "description": "A nodejs module to query TRAPI Query Graph", "main": "built/index.js", "scripts": { @@ -36,24 +36,24 @@ "homepage": "https://github.com/kevinxin90/bte_trapi_query_graph_handler#readme", "devDependencies": { "@types/debug": "^4.1.5", - "@types/jest": "^26.0.20", - "@types/node": "^14.14.33", + "@types/jest": "^26.0.21", + "@types/node": "^14.14.35", "coveralls": "^3.1.0", "jest": "^26.6.3", "prettier": "^2.2.1", "redis-mock": "^0.56.3", "standard-version": "^9.1.0", - "ts-jest": "^26.5.3", + "ts-jest": "^26.5.4", "tslint": "^6.1.3", "tslint-config-prettier": "^1.18.0", - "typedoc": "^0.20.30", + "typedoc": "^0.20.33", "typescript": "^4.2.3" }, "dependencies": { - "@biothings-explorer/call-apis": "^1.14.0", + "@biothings-explorer/call-apis": "^1.15.0", "@biothings-explorer/smartapi-kg": "^3.1.1", "biolink-model": "^0.3.0", - "biomedical_id_resolver": "^3.3.0", + "biomedical_id_resolver": "^3.4.1", "debug": "^4.3.1", "lodash": "^4.17.21", "ms": "^2.1.3",