Neo4j:如何将变量传递给 Neo4j Apoc (apoc.path.subgraphAll) 属性

Neo4j: How to pass a variable to Neo4j Apoc (apoc.path.subgraphAll) Property

我是 Neo4j 的新手,正在尝试通过为企业参考/集成架构(架构将所有企业应用程序显示为节点、底层表/API - 逻辑上分组为节点、应用程序之间的集成为关系)实现图数据库.

Objective 是利用 Graph DB 的力量无缝实现 'Impact Analysis'(注意:我知道这可能是实现我想要实现的任何目标的不正确方法,因此欢迎提出建议)

现在让我来简要说明一下我的问题,

有四个应用——A1、A2、A3、A4; A1 有一组表(由节点 A1TS1 表示)由集成 1(在本例中为关系)更新,集成 2 读取同一组 table。因此数据模型如下所示

(A1TS1)<-[:INT1]-(A1)<-[:INT1]-(A2)
(A1TS1)-[:INT2]->(A1)-[:INT2]->(A4)

我在 A1TS1 节点中将底层应用程序 table 名称捕获为列表 属性。

假设其中一个应用程序 table 更改为新列或数据类型,我想了解所有受影响的集成和应用程序。现在我正在尝试编写如下查询以检索所有节点和关系 associated/impacted 由于此 table 更改但我无法实现此

预期结果是 - 所有受影响的节点(A1TS1、A1、A2、A4)和关系(INT1、INT2)

选项 1(使用 APOC)

MATCH (a {TCName:'A1TS1',AppName:'A1'})-[r]-(b) 
WITH a as STRTND, Collect(type(r)) as allr 
CALL apoc.path.subgraphAll(STRTND, {relationshipFilter:allr}) YIELD nodes, relationships 
RETURN nodes, relationships

此失败错误 Failed to invoke procedure 'apoc.path.subgraphAll': Caused by: java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.lang.String

选项 2(使用 with、unwind、collect 子句)

MATCH (a {TCName:'A1TS1',AppName:'A1'})-[r]-(b) 
WITH a as STRTND, Collect(r) as allr 
UNWIND allr as rels 
MATCH p=()-[rels]-()-[rels]-() 
RETURN p

这失败并出现错误 "Cannot use the same relationship variable 'rels' for multiple patterns" 但是如果我像 p=()-[rels]=() 那样使用 [rels] 一次,它可以工作但不会产生所有节点

任何 help/suggestion/lead 表示赞赏。提前致谢

更新 尝试提供更多背景信息 显示基础数据

MATCH (TC:TBLCON) RETURN TC

"TC"
{"Tables":["TBL1","TBL2","TBL3"],"TCName":"A1TS1","AppName":"A1"}  
{"Tables":["TBL4","TBL1"],"TCName":"A2TS1","AppName":"A2"} 

MATCH (A:App) RETURN A

"A"                                                                   
{"Sponsor":"XY","Platform":"Oracle","TechOwnr":"VV","Version":"12","Tags":["ERP","OracleEBS","FinanceSystem"],"AppName":"A1"}               
{"Sponsor":"CC","Platform":"Teradata","TechOwnr":"RZ","Tags":["EDW","DataWarehouse"],"AppName":"A2"}   

MATCH ()-[r]-() RETURN distinct r.relname

"r.relname"
"FINREP"   │  (runs between A1 to other apps)
"UPFRNT"   │  (runs between A2 to different Salesforce App)
"INVOICE"  │  (runs between A1 to other apps)

有了这个,这就是我要实现的目标 假设 "TBL3" 在应用程序 A1 中被更改,我想编写一个查询,在匹配模式中指定 table "TBL3",获取所有关联关系和连接节点(上游)

可能我需要分三步完成, 第 1 步 - 编写匹配模式以查找起始节点和关联关系 第 2 步 - 将第 1 步中的关系存储在数组变量/参数中 第 3 步 - 将第 1 步的起始节点和第 2 步的参数传递给 apoc.path.subgraphAll 以查看所有受影响的节点

这在概念上听起来可能有效,但问题是如何在 neo4j Cypher 查询中从技术上做到这一点。

希望对您有所帮助

此查询可能会执行您想要的操作:

MATCH (tc:TBLCON)
WHERE $table IN tc.Tables
MATCH p=(tc)-[:Foo*]-()
WITH tc,
  REDUCE(s = [], x IN COLLECT(NODES(p)) | s + x) AS ns,
  REDUCE(t = [], y IN COLLECT(RELATIONSHIPS(p)) | t + y) AS rs
UNWIND ns AS n
WITH tc, rs, COLLECT(DISTINCT n) AS nodes
UNWIND rs AS rel
RETURN tc, nodes, COLLECT(DISTINCT rel) AS rels;

它假定您提供感兴趣的 table 的名称(例如,"TBL3")作为 table parameter 的值。它还假定感兴趣的关系都具有 Foo 类型。

它首先找到 tc,包含 table 名称的 TBLCON 个节点。然后它使用 variable-length non-directional search for all paths (with non-repeating relationships) that include tc. It then uses COLLECT twice: to aggregate 每个路径中的节点列表,并聚合每个路径中的关系列表。每个聚合结果将是一个列表列表,因此它在每个外部列表上使用 REDUCE 来合并内部列表。然后它在每个列表上使用 UNWINDCOLLECT(DISTINCT x) 来生成具有唯一元素的列表。

[更新]

如果您按类型(而不是按 属性 值)区分关系,则通过利用 APOC 函数,您的 Cypher 代码可以简单得多。以下查询假定所需的关系类型是通过 types 参数传递的:

MATCH (tc:TBLCON)
WHERE $table IN tc.Tables
CALL apoc.path.subgraphAll(
  tc, {relationshipFilter: apoc.text.join($types, '|')}) YIELD nodes, relationships
RETURN nodes, relationships;

根据 cybersam 的回复,下面的查询让我得到了我想要的。唯一的限制是,此结果仅限于 3 层(第 3 层通过可选匹配)

MATCH (TC:TBLCON) WHERE 'TBL3' IN TC.Tables 
CALL apoc.path.subgraphAll(TC, {maxLevel:1}) YIELD nodes AS invN, relationships AS invR
WITH TC, REDUCE (tmpL=[], tmpr IN invR | tmpL+type(tmpr)) AS impR
MATCH FLP=(TC)-[]-()-[FLR]-(SL) WHERE type(FLR) IN impR 
WITH FLP, TC, SL,impR 
OPTIONAL MATCH SLP=(SL)-[SLR]-() WHERE type(SLR) IN impR RETURN FLP,SLP

这适合我的需要,希望这也能帮助到别人。

感谢大家的回复和建议

****更新****

增强了查询以摆脱可选匹配条件和其他给定限制

MATCH (initTC:TBLCON) WHERE $TL IN initTC.Tables 
WITH Reduce(O="",OO in Reduce (I=[], II in collect(apoc.node.relationship.types(initTC)) | I+II) | O+OO+"|") as RF
MATCH (TC:TBLCON) WHERE $TL IN TC.Tables 
CALL apoc.path.subgraphAll(TC,{relationshipFilter:RF}) YIELD nodes, relationships
RETURN nodes, relationships

谢谢大家(尤其是 cybersam)