我有一个标签图,它们彼此相关.我的目标是创建一个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)相关的标签.
我知道我可以连接MATCH和WITH声明,并做这样的事情:
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).
那么有没有办法在一个查询中创建它,类似于我的第一次尝试?
这是一个只需要一个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集合已包含不同的节点,因此结果还必须具有不同的节点.此外,如果您有很多标签,上述查询可以通过以下方式加快:
:Tag(name)在查询中指定使用该索引 - 在MATCH和子句之间插入以下子句WHERE.目前,Cypher引擎不会自动使用此特定查询的索引.
USING INDEX t:Tag(name)
Run Code Online (Sandbox Code Playgroud)