从现有节点的子集创建图形

Create graph from subset of existing nodes

我有一个包含 2 种节点的有向 Neo4j 图:第 1 组中带有标签的节点和第 2 组中带有标签的节点。我想在 Set 中的节点之间创建新的(新类型的)边1,只要存在从 Set 1 节点到另一个 Set 1 节点的定向路径,该路径仅通过 Set 2 节点(可能有 0 个这样的 Set 2 节点)。

这是一个示例数据集:

CREATE (a:A {id:"a"})-[:CONN]->(t1:T {id:"t1"}),
   (t1)-[:CONN]->(b1:B {id:"b1"}),
   (b1)-[:CONN]->(t2:U {id:"t1"}),
   (t2)-[:CONN]->(c1:C {id:"c1"}),
   (c1)-[:CONN]->(t3:T {id:"t3"}),
   (t3)-[:CONN]->(d1:D {id:"d1"}),
   (t3)-[:CONN]->(d2:D {id:"d2"}),
   (d1)-[:CONN]->(t4:T {id:"t4"}),
   (d2)-[:CONN]->(t4),
   (t4)-[:CONN]->(e1:E {id:"e1"}),
   (t4)-[:CONN]->(e2:E {id:"e2"})

在此示例中,ABCDE 在第 1 组中,T & U 在第 2 组中,所以我想像这样绘制新的 :AGG 边:

MATCH (a:A {id:"a"}), (b1:B {id:"b1"}), (c1:C {id:"c1"}), (d1:D {id:"d1"}),
      (d2:D {id:"d2"}), (e1:E {id:"e1"}), (e2:E {id:"e2"})
CREATE (a)-[:AGG]->(b1),
   (b1)-[:AGG]->(c1),
   (c1)-[:AGG]->(d1),
   (c1)-[:AGG]->(d2),
   (d1)-[:AGG]->(e1),
   (d1)-[:AGG]->(e2),
   (d2)-[:AGG]->(e1),
   (d2)-[:AGG]->(e2)

关于 CONN 条边,我知道该图是一个 DAG,所以我不必担心循环。

这可以在 Cypher 中完成吗?或者有人可以通过 Java 接口建议一种有效的方法(例如遍历策略)?谢谢。

是的,它可以完成 - 这是一个复杂的查询,因此您可能需要稍微尝试一下,但这里有一些可以开始的东西。也许其他人可以对此进行改进,但我认为这应该可以完成大部分基本逻辑。

MATCH p=(node1)-[*]-(node2)
WHERE ('A' in labels(node1) OR
       'B' in labels(node1) OR
       'C' in labels(node1) OR
       'D' in labels(node1) OR
       'E' in labels(node1)) 
      AND
      ('A' in labels(node2) OR
       'B' in labels(node2) OR
       'C' in labels(node2) OR
       'D' in labels(node2) OR
       'E' in labels(node2)) 
      AND
      (length(p) = 1 OR 
       all(intermedNode in 
           filter(n IN tail(nodes(p)) WHERE n <> last(nodes(p)))
           WHERE
           ('T' in labels(intermedNode) OR
            'U' in labels(intermedNode))))
WITH node1, node2
CREATE node1-[:MyNewNiftyEdge]->node2;

解释:

  1. 我们正在寻找路径;前两个大 WHERE 块只是证明路径的源和目标都必须在 "Set1".
  2. WHERE 块的最后一部分做了所有有趣的事情。长度为 1 的路径是可以的(零个中间 "Set2" 节点)。但是如果有中间节点,我们要做的是检查是否所有 "internal" 个节点都是 "Set2"。带有 tail 表达式的 filter 位只是从路径中切掉第一个和最后一个节点(我们已经知道那是 node1node2)。然后 all 表达式坚持如果中间有任何东西,它必须是一个 Set2 节点(标记为 "T" 或 "U")。
  3. 最后,对于这两个匹配的节点,我们创建了一个直接连接它们的漂亮的新关系。