Neo4j匹配与集合中所有节点相关的节点

lma*_*gon 1 neo4j cypher

我有一个标签图,它们彼此相关.我的目标是创建一个Cypher查询,它将通过1或2跳返回与输入标签数组相关的所有标签.

我提出了一个查询,这个查询并不像预期的那样有效.

MATCH (t:Tag)
WHERE t.name IN ["A", "B", "C"]
WITH t
MATCH (a:Tag)-[:RELATED*1..2]-(t)
RETURN DISTINCT a;
Run Code Online (Sandbox Code Playgroud)

此查询首先找到的节点A,B,C然后搜索代码,该相关的A,B C通过1个节点或更小.

我想要做的是找到与所有三个节点(A,B C)相关的标签.


我知道我可以连接MATCHWITH声明,并做这样的事情:

MATCH (t:Tag)-[:RELATED*1..2]-(a:Tag)
WHERE t.name="A"

WITH DISTINCT a
MATCH (t:Tag)-[:RELATED*1..2]-(a)
WHERE t.name="B"

WITH DISTINCT a
MATCH (t:Tag)-[:RELATED*1..2]-(a)
WHERE t.name="C"
...
RETURN DISTINCT a;
Run Code Online (Sandbox Code Playgroud)

但它运行非常缓慢,当输入的数量增加标签(在这种情况下,只有3输入标签:A,B,C).


那么有没有办法在一个查询中创建它,类似于我的第一次尝试?

cyb*_*sam 5

这是一个只需要一个MATCH子句的解决方案.

MATCH (t:Tag)-[:RELATED*..2]-(other:Tag)
WHERE t.name IN ["A", "B", "C"]
WITH t, COLLECT(DISTINCT other) AS others
WITH COLLECT(others) AS coll
RETURN FILTER(x IN coll[0] WHERE ALL(y IN coll[1..] WHERE x IN y)) AS res;
Run Code Online (Sandbox Code Playgroud)
  • 查询查找other与每个命名标记(t)"相关"(最多2步)的所有标记().
  • 然后,它使用聚合来为每个节点收集不同的 other节点t.在这个例子中,我们最终得到3个others集合 - 每个集合1个t.需要注意的重要一点是查询结果是每个 others集合的交集.
  • 然后它将所有others集合收集到一个coll集合中.
  • 最后,由于结果集是每个others集合的交集,因此查询遍历第一个others集合中的节点,并提取同样位于其余others集合中的节点.并且,由于每个others集合已包含不同的节点,因此结果还必须具有不同的节点.

此外,如果您有很多标签,上述查询可以通过以下方式加快:

  1. on ,然后创建索引(或唯一性约束,自动为您创建索引):Tag(name)
  2. 在查询中指定使用该索引 - 在MATCH和子句之间插入以下子句WHERE.目前,Cypher引擎不会自动使用此特定查询的索引.

    USING INDEX t:Tag(name)
    
    Run Code Online (Sandbox Code Playgroud)