diff --git a/client/src/types/typesLex.ts b/client/src/types/typesLex.ts index ca63a24a..62f28c0e 100644 --- a/client/src/types/typesLex.ts +++ b/client/src/types/typesLex.ts @@ -18,7 +18,8 @@ export interface QueryFieldEntry { order?: number, // used to sort fields // baseType/lexType defines the type conversion required from/to base/lex types baseType: LexConvertType, - lexType: LexConvertType + lexType: LexConvertType, + queryFunctionConfig?: any, } export type QueryFieldMap = Record diff --git a/client/src/utils/BGraphQueryUtil.ts b/client/src/utils/BGraphQueryUtil.ts index ca1d25a0..57e5903f 100644 --- a/client/src/utils/BGraphQueryUtil.ts +++ b/client/src/utils/BGraphQueryUtil.ts @@ -42,17 +42,6 @@ const bioPathPost = (bgraphPathQuery, clause: Filter): any => { // EDGE QUERIES // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioEdgeTested = (bgraphPathQuery, clause: Filter): any => { - return bgraphPathQuery.filter(document => { - if (document._type === 'edge') { - const edge = document; - return edge.tested === Boolean(clause.values[0]); - } - // Document is not an edge - return false; - }); -}; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types const bioEdgeType = (bgraphPathQuery, clause: Filter): any => { return bgraphPathQuery.filter(document => { if (document._type === 'edge') { @@ -80,20 +69,47 @@ const bioEdgeDOI = (bgraphPathQuery, clause: Filter): any => { }; // NODE QUERIES -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioNodeName = (bgraphPathQuery, clause: Filter): any => { - let names = clause.values as string[]; - // Filter matching case insensitive names - names = names.map(name => name.toLowerCase()); - return bgraphPathQuery.filter(document => { - if (document._type === 'node') { - const node = document; - return names.some(name => name === node.name.toLowerCase()); + +const propertyMatchQueryFactory = (config: any): (bgQuery: any, clause: Filter) => any => { + return (bgQuery: any, clause: Filter): any => { + let values = clause.values; + + if (config.matchType === 'string' && config.toLowerCase) { + values = values.map(v => { + if (typeof v === 'string') { + return v.toLowerCase(); + } else { + return v; + } + }); } - // Document is not a node - return false; - }); + + return bgQuery.filter(document => { + if (document._type === config.documentType) { + if (config.matchType === 'string') { + return values.some(v => { + let documentProperty = document[config.property]; + if (config.toLowerCase) documentProperty = documentProperty.toLowerCase(); + if (config.includes) { + return documentProperty.includes(v); + } else { + return v === documentProperty; + } + }); + } else if (config.matchType === 'boolean') { + return document[config.property] === Boolean(values[0]); + } else if (config.matchType === 'number') { + return values.some(v => { + return document[config.property] === Number(v); + }); + } + } + // Document is not specified document type + return false; + }); + }; }; + // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types const bioNodeGroup = (bgraphPathQuery, clause: Filter): any => { return bgraphPathQuery.filter(document => { @@ -105,50 +121,6 @@ const bioNodeGroup = (bgraphPathQuery, clause: Filter): any => { return false; }); }; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioNodeGrounded = (bgraphPathQuery, clause: Filter): any => { - return bgraphPathQuery.filter(document => { - if (document._type === 'node') { - const node = document; - return node.grounded_db === Boolean(clause.values[0]); - } - // Document type is an edge - return false; - }); -}; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioNodeGroundedOnto = (bgraphPathQuery, clause: Filter): any => { - return bgraphPathQuery.filter(document => { - if (document._type === 'node') { - const node = document; - return node.grounded_group === Boolean(clause.values[0]); - } - // Document type is an edge - return false; - }); -}; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioNodeInDegree = (bgraphPathQuery, clause: Filter): any => { - return bgraphPathQuery.filter(document => { - if (document._type === 'node') { - const node = document; - return clause.values.some(value => node.in_degree === Number(value)); - } - // Document type is an edge - return false; - }); -}; -// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types -const bioNodeOutDegree = (bgraphPathQuery, clause: Filter): any => { - return bgraphPathQuery.filter(document => { - if (document._type === 'node') { - const node = document; - return clause.values.some(value => node.out_degree === Number(value)); - } - // Document type is an edge - return false; - }); -}; const docsClustersNodeTitle = (bgraphPathQuery, clause: Filter): any => { let titles = clause.values as string[]; @@ -260,7 +232,7 @@ export const executeBgraphEdges = (bgraphEdgeQuery, clause: Filter): any => { switch (clause.field) { // EDGE CLAUSES case QUERY_FIELDS_MAP.BIO_EDGE_PRE.field: return bgraphEdgeQuery; - case QUERY_FIELDS_MAP.BIO_EDGE_TESTED.field: return bioEdgeTested(bgraphEdgeQuery, clause); + case QUERY_FIELDS_MAP.BIO_EDGE_TESTED.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_EDGE_TESTED.queryFunctionConfig)(bgraphEdgeQuery, clause); case QUERY_FIELDS_MAP.BIO_EDGE_TYPE.field: return bioEdgeType(bgraphEdgeQuery, clause); case QUERY_FIELDS_MAP.BIO_EDGE_DOI.field: return bioEdgeDOI(bgraphEdgeQuery, clause); case QUERY_FIELDS_MAP.BIO_EDGE_POST.field: return bgraphEdgeQuery.as('edgeOnly').out().as('target').back('edgeOnly').in().as('source').merge('edgeOnly', 'source', 'target'); @@ -276,15 +248,15 @@ export const executeBgraphPathQuery = (bgraphPathQuery, clause: Filter): any => case QUERY_FIELDS_MAP.BIO_PATH_PRE.field: return bioPathPre(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_PATH_PRE_NODE_FILTER_LOOP.field: return bioPathPreNodeFilterLoop(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_PATH_PRE_EDGE_FILTER_LOOP.field: return bioPathPreEdgeFilterLoop(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_EDGE_TESTED.field: return bioEdgeTested(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_EDGE_TESTED.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_EDGE_TESTED.queryFunctionConfig)(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_EDGE_TYPE.field: return bioEdgeType(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_EDGE_DOI.field: return bioEdgeDOI(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_NAME.field: return bioNodeName(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_NAME.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_NAME.queryFunctionConfig)(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_NODE_GROUP.field: return bioNodeGroup(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.field: return bioNodeGrounded(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.field: return bioNodeGroundedOnto(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.field: return bioNodeInDegree(bgraphPathQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.field: return bioNodeOutDegree(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.queryFunctionConfig)(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.queryFunctionConfig)(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.queryFunctionConfig)(bgraphPathQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.queryFunctionConfig)(bgraphPathQuery, clause); case QUERY_FIELDS_MAP.BIO_PATH_POST.field: return bioPathPost(bgraphPathQuery, clause); // EPI PATH CLAUSES case QUERY_FIELDS_MAP.EPI_PATH_PRE.field: return epiPathPre(bgraphPathQuery, clause); @@ -300,12 +272,12 @@ export const executeBgraphNodes = (bgraphNodeQuery: any, clause: Filter): any => switch (clause.field) { // NODE CLAUSES case QUERY_FIELDS_MAP.BIO_NODE_PRE.field: return bgraphNodeQuery; - case QUERY_FIELDS_MAP.BIO_NODE_NAME.field: return bioNodeName(bgraphNodeQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_NAME.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_NAME.queryFunctionConfig)(bgraphNodeQuery, clause); case QUERY_FIELDS_MAP.BIO_NODE_GROUP.field: return bioNodeGroup(bgraphNodeQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.field: return bioNodeGrounded(bgraphNodeQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.field: return bioNodeGroundedOnto(bgraphNodeQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.field: return bioNodeInDegree(bgraphNodeQuery, clause); - case QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.field: return bioNodeOutDegree(bgraphNodeQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_GROUNDED.queryFunctionConfig)(bgraphNodeQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_GROUNDED_ONTO.queryFunctionConfig)(bgraphNodeQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_IN_DEGREE.queryFunctionConfig)(bgraphNodeQuery, clause); + case QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.field: return propertyMatchQueryFactory(QUERY_FIELDS_MAP.BIO_NODE_OUT_DEGREE.queryFunctionConfig)(bgraphNodeQuery, clause); case QUERY_FIELDS_MAP.BIO_NODE_POST.field: return bgraphNodeQuery; // DOC CLAUSES // TODO: Currently we are using the BIO_NODE_PRE/POST for document cluster queries diff --git a/client/src/utils/QueryFieldsUtil.ts b/client/src/utils/QueryFieldsUtil.ts index 403f80a9..9e7f73c5 100644 --- a/client/src/utils/QueryFieldsUtil.ts +++ b/client/src/utils/QueryFieldsUtil.ts @@ -58,18 +58,34 @@ const QUERY_FIELDS_MAP: QueryFieldMap = { ..._searchable('Node Name', false), baseType: 'string', lexType: 'string', + queryFunctionConfig: { + documentType: 'node', + property: 'name', + matchType: 'string', + toLowerCase: true, + }, }, BIO_NODE_GROUNDED: { ..._field('bioNodeGrounded', 'Node Grounded'), ..._searchable('Node Grounded', false), baseType: 'integer', lexType: 'integer', + queryFunctionConfig: { + documentType: 'node', + property: 'grounded_db', + matchType: 'boolean', + }, }, BIO_NODE_GROUNDED_ONTO: { ..._field('bioNodeGroundedOnto', 'Node Grounded Onto'), ..._searchable('Node Grounded Onto', false), baseType: 'integer', lexType: 'integer', + queryFunctionConfig: { + documentType: 'node', + property: 'grounded_group', + matchType: 'boolean', + }, }, BIO_NODE_GROUP: { ..._field('bioNodeGroup', 'Node Group'), @@ -82,12 +98,22 @@ const QUERY_FIELDS_MAP: QueryFieldMap = { ..._searchable('Node In-degree', false), baseType: 'integer', lexType: 'integer', + queryFunctionConfig: { + documentType: 'node', + property: 'in_degree', + matchType: 'number', + }, }, BIO_NODE_OUT_DEGREE: { ..._field('bioNodeOutDegree', 'Node Out-degree'), ..._searchable('Node Out-degree', false), baseType: 'integer', lexType: 'integer', + queryFunctionConfig: { + documentType: 'node', + property: 'out_degree', + matchType: 'number', + }, }, BIO_NODE_POST: { ..._field('bioNodePost', 'Node Post'), @@ -119,6 +145,11 @@ const QUERY_FIELDS_MAP: QueryFieldMap = { ..._searchable('Edge Tested', false), baseType: 'integer', lexType: 'integer', + queryFunctionConfig: { + documentType: 'edge', + property: 'tested', + matchType: 'boolean', + }, }, BIO_EDGE_DOI: { ..._field('bioEdgeDoi', 'Edge DOI'),