neo4j – 查找具有共同二级关系的所有节点子树

我正在处理Neo4J数据库中的物料清单(BOM)和零件数据.

我的图表中有3种类型的节点:

>(ItemUsageInstance)这些是物料清单树的元素
>(项目)BOM表树上的每个唯一项目都存在一个
>(材料)

关系是:

>(ItemUsageInstance) – [CHILD_OF] – >(ItemUsageInstance)
>(ItemUsageInstance) – [INSTANCE_OF] – >(项目)
>(项目) – [MADE_FROM] – >(材料)

架构如下图所示:

《neo4j – 查找具有共同二级关系的所有节点子树》

这是数据的简化图. (重新定位节点以增强可见性的图表):

《neo4j – 查找具有共同二级关系的所有节点子树》

我想要做的是查找相邻ItemUsageInstances的子树,其Itemss全部来自相同的材料

我到目前为止的查询是:

MATCH (m:Material)
WITH m AS m
MATCH (m)<-[:MADE_FROM]-(i1:Item)<-[]-(iui1:ItemUsageInstance)-[:CHILD_OF]->(iui2:ItemUsageInstance)-[]->(i2:Item)-[:MADE_FROM]->(m) RETURN iui1, i1, iui2, i2, m

但是,这仅返回一个这样的子树,图中间的相邻节点具有公共材料“M0002”.此外,结果的行是单独的条目,一个用于子树中的每个父子对:

╒══════════════════════════╤══════════════════════╤══════════════════════════╤══════════════════════╤═══════════════════════╕
│"iui1"                    │"i1"                  │"iui2"                    │"i2"                  │"m"                    │
╞══════════════════════════╪══════════════════════╪══════════════════════════╪══════════════════════╪═══════════════════════╡
│{"instance_id":"inst5002"}│{"part_number":"p003"}│{"instance_id":"inst7003"}│{"part_number":"p004"}│{"material_id":"M0002"}│
├──────────────────────────┼──────────────────────┼──────────────────────────┼──────────────────────┼───────────────────────┤
│{"instance_id":"inst7002"}│{"part_number":"p003"}│{"instance_id":"inst7003"}│{"part_number":"p004"}│{"material_id":"M0002"}│
├──────────────────────────┼──────────────────────┼──────────────────────────┼──────────────────────┼───────────────────────┤
│{"instance_id":"inst7001"}│{"part_number":"p002"}│{"instance_id":"inst7002"}│{"part_number":"p003"}│{"material_id":"M0002"}│
└──────────────────────────┴──────────────────────┴──────────────────────────┴──────────────────────┴───────────────────────┘

我期待第二个子树,它恰好也是一个链表,包括在内.第二个子树由图表最右侧的ItemUsageInstances inst7006,inst7007,inst7008组成.对于它的价值,不仅这些相邻的实例由相同的材料制成,它们都是同一个项目的实例.

我确认每个ItemUsageInstance节点都与Item节点有[INSTANCE_OF]关系:

MATCH (iui:ItemUsageInstance) WHERE NOT (iui)-[:INSTANCE_OF]->(:Item) RETURN iui 

(返回0条记录).

还确认每个Item节点都与Material节点有[MADE_FROM]关系:

MATCH (i:Item) WHERE NOT (i)-[:MADE_FROM]->(:Material) RETURN i 

(返回0条记录).

确认inst7008是唯一没有传出[CHILD_OF]关系的ItemUsageInstance.

MATCH (iui:ItemUsageInstance) WHERE NOT (iui)-[:CHILD_OF]->(:ItemUsageInstance) RETURN iui

(返回1条记录:{“instance_id”:“inst7008”})

inst5000和inst7001是唯一没有传入[CHILD_OF]关系的ItemUsageInstances

MATCH (iui:ItemUsageInstance) WHERE NOT (iui)<-[:CHILD_OF]-(:ItemUsageInstance) RETURN iui

(返回2条记录:{“instance_id”:“inst7001”}和{“instance_id”:“inst5000”})

我想收集/汇总结果,以便每一行都是一个子树.我看到this example如何收集()并使数组方法工作.但它仍然有重复的ItemUsageInstances. (那里讨论的“物品地图”完全失败了…)

有关为什么我的查询只找到具有相同材料的相邻项目用法实例的一个子树的任何见解?

通过子树聚合结果的最佳方法是什么?

最佳答案 找到根源很容易. MATCH(root:ItemUsageInstance)WHERE NOT() – [:CHILD_OF] – >(root)

对于孩子,您可以通过指定最小距离0(默认值为1)来包含根.

MATCH p =(root) – [:CHILD_OF * 0..25] – >(ins),(m:Material)< – [:MADE_FROM] – (:Item)< – [:INSTANCE_OF] – (ins ) 然后假设每个实例只有一个项目材料,根据材料聚合所有内容(您不能在聚合中聚合,因此在使用节点收集深度之前使用WITH获取深度) WITH ins,SIZE(NODES(p))作为深度,m RETURN COLLECT({node:ins,depth:depth})作为实例,m作为素材 所以,一起来

MATCH (root:ItemUsageInstance),
      p=(root)<-[:CHILD_OF*0..25]-(ins),
      (m:Material)<-[:MADE_FROM]-(:Item)<-[:INSTANCE_OF]-(ins)
WHERE NOT ()<-[:CHILD_OF]-(root)
  AND NOT (m:Material)<-[:MADE_FROM]-(:Item)<-[:INSTANCE_OF]-()<-[:CHILD_OF]-(ins)
MATCH p2=(ins)<-[:CHILD_OF*1..25]-(cins)
WHERE ALL(n in NODES(p2) WHERE (m)<-[:MADE_FROM]-(:Item)<-[:INSTANCE_OF]-(n))
WITH ins, cins, SIZE(NODES(p2)) as depth, m ORDER BY depth ASC
RETURN ins as collection_head, ins+COLLECT(cins) as instances, m as material
点赞