我正在使用Neo4J数据库中的物料清单(BOM)和零件数据。

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


(ItemUsageInstance)这些是物料清单树的元素
(Item) BOM表树中的每个唯一项都存在一个
(Material)


关系是:


(ItemUsageInstance)-[CHILD_OF]->(ItemUsageInstance)
(ItemUsageInstance)-[INSTANCE_OF]->(Item)
(Item)-[MADE_FROM]->(Material)


该架构如下图所示:

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

这是数据的简化图。 (已重新放置节点以增强可见性的图):

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

我想做的是查找相邻ItemUsageInstance的子树,这些子树的Items都由相同的Material组成

我到目前为止的查询是:

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


但是,这仅返回一个这样的子树,即图中间的相邻节点,它们的公共Material为“ 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组成。就其价值而言,这些相邻实例不仅由相同的Material组成,而且都是相同Item的所有实例。

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

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


(返回0条记录)。

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

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


(返回0条记录)。

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

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


(返回1条记录:{"instance_id":"inst7008"}

inst5000inst7001是唯一没有传入ItemUsageInstances关系的[CHILD_OF]

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


(返回2条记录:{"instance_id":"inst7001"}{"instance_id":"inst5000"}

我想收集/汇总结果,以便每一行都是一个子树。我看到了this example如何使用collect()的方法,并使数组方法起作用。但是它中仍然有重复的ItemUsageInstance。 (在那里讨论的“项目图”完全失败了……)

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

按子树汇总结果的最佳方法是什么?

最佳答案

寻找根源很容易。 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)

然后,假设每个实例仅包含一个item-material,则基于材质聚合所有内容(您无法聚合到一个聚合中,因此在使用节点收集深度之前,请使用WITH获取深度)

WITH ins, SIZE(NODES(p)) as depth, m RETURN COLLECT({node:ins, depth:depth}) as instances, m as material



所以,一起

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

关于neo4j - 查找具有共同第二级关系的节点的所有子树,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51452624/

10-14 12:04