Neo4j匹配与集合中所有节点相关的节点
我有一个标签图,它们相互关联。我的目标是创建一个Cypher查询,它将通过1或2跳返回与输入标记数组相关的所有标记 我提出了一个问题,但没有达到预期效果Neo4j匹配与集合中所有节点相关的节点,neo4j,cypher,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; 此查询首先查找节点A、B、C,然后通过1个或更少的节点搜索与A、B或C相关的标记 不过我想做的是找到与所有三个节点(A、B和C)相关
MATCH (t:Tag)
WHERE t.name IN ["A", "B", "C"]
WITH t
MATCH (a:Tag)-[:RELATED*1..2]-(t)
RETURN DISTINCT a;
此查询首先查找节点A
、B
、C
,然后通过1个或更少的节点搜索与A
、B
或C
相关的标记
不过我想做的是找到与所有三个节点(A
、B
和C
)相关的标记
我知道我可以用语句连接
匹配
和,并执行如下操作:
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;
但是,当输入标记的数量增加时,它运行得非常慢(在这种情况下,只有3个输入标记:A
,B
,C
)
那么,有没有一种方法可以在一个查询中实现它,类似于我的第一次尝试?这个如何:
MATCH (t:Tag)-[:RELATED*1..2]-(other:Tag)
WHERE t.name IN ["A", "B", "C"]
WITH t, collect(other.name) as others
WHERE ALL(x in ["A","B","C"] WHERE x in others)
RETURN t
诀窍是将t
的所有相关节点放入一个集合(其他)中,并使用all
谓词确保所有的a、B和C都是该集合的一部分。这个怎么样:
MATCH (t:Tag)-[:RELATED*1..2]-(other:Tag)
WHERE t.name IN ["A", "B", "C"]
WITH t, collect(other.name) as others
WHERE ALL(x in ["A","B","C"] WHERE x in others)
RETURN t
诀窍是将t
的所有相关节点放入一个集合(其他)中,并使用all
谓词确保所有a、B和C都是该集合的一部分。这里有一个解决方案,它只需要一个匹配
子句
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;
- 查询将查找与每个命名标记(
t
)相关(最多两步)的所有标记(other
)
- 然后,它使用聚合为每个
t
收集不同的其他
节点。在本例中,我们最终得到了3个others
集合——每个t
集合1个
- 然后,它将所有
others
集合收集到单个coll
集合中
- 最后,由于结果集应该是每个
others
集合的交集,因此查询遍历第一个others
集合中的节点,并提取其余others
集合中的节点。而且,由于每个others
集合已经包含不同的节点,因此结果也必须具有不同的节点
此外,如果您有很多标记,可以通过以下方式加快上述查询:
(或,它会自动为您创建索引)在:Tag(name)
,然后
在查询中指定该索引的使用——在MATCH
和WHERE
子句之间插入以下子句。目前,Cypher引擎不会自动将索引用于此特定查询
USING INDEX t:Tag(name)
这里是一个只需要一个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;
- 查询将查找与每个命名标记(
t
)相关(最多两步)的所有标记(other
)
- 然后,它使用聚合为每个
t
收集不同的其他
节点。在本例中,我们最终得到了3个others
集合——每个t
集合1个
- 然后,它将所有
others
集合收集到单个coll
集合中
- 最后,由于结果集应该是每个
others
集合的交集,因此查询遍历第一个others
集合中的节点,并提取其余others
集合中的节点。而且,由于每个others
集合已经包含不同的节点,因此结果也必须具有不同的节点
此外,如果您有很多标记,可以通过以下方式加快上述查询:
(或,它会自动为您创建索引)在:Tag(name)
,然后
在查询中指定该索引的使用——在MATCH
和WHERE
子句之间插入以下子句。目前,Cypher引擎不会自动将索引用于此特定查询
USING INDEX t:Tag(name)
这里有一个替代方案:
MATCH shortestPath((t:Tag)<-[:RELATED*1..2]-(source:Tag)) //make sure there are no duplicate paths
WHERE source.name IN ["A","B","C"] AND NOT source.name = t.name //shortest path for identical node would throw an exception
WITH COLLECT(t) as tags //all tags that were reachable, with duplicates for reachable from multiple tags
UNWIND tags as tag //for each tag
WITH tag, tags //using with as match would be a drastic slowdown
WHERE size(filter(t IN tags WHERE ID(t) = ID(tag))) = 3 //if it is connected to all three, it must have been matched three times
RETURN DISTINCT m //since any match will still be in there 3 (or n) times
匹配最短路径((t:Tag)这里有一个替代方案:
MATCH shortestPath((t:Tag)<-[:RELATED*1..2]-(source:Tag)) //make sure there are no duplicate paths
WHERE source.name IN ["A","B","C"] AND NOT source.name = t.name //shortest path for identical node would throw an exception
WITH COLLECT(t) as tags //all tags that were reachable, with duplicates for reachable from multiple tags
UNWIND tags as tag //for each tag
WITH tag, tags //using with as match would be a drastic slowdown
WHERE size(filter(t IN tags WHERE ID(t) = ID(tag))) = 3 //if it is connected to all three, it must have been matched three times
RETURN DISTINCT m //since any match will still be in there 3 (or n) times
匹配最短路径((t:Tag)您查询的语法不正确-请看WHERE ALL
语句,它没有真正的意义。仍然感谢您的尝试,我将研究ALL
谓词,也许它会解决我的问题。我刚刚用正确的语句更新了我的答案。恐怕您误解了问题。我不想确定在A
,B
和C
在集合中(其他),但我正试图找到同时连接到A
、B
和C
的所有其他节点。因此,例如,如果节点D
与所有三个输入节点都有关系,则它将位于输出中。此外,如果节点E
仅连接到A
A
B
,B但如果不是C
,那么它就不会出现在输出中。我问题中的第二个查询实际上是有效的,并且符合我的要求,因此它应该解释我需要什么。但它不必要地复杂,我认为存在一个更简单的解决方案。仅此而已:)您查询的语法不正确-请看WHERE ALL
语句,它没有真正的意义。仍然感谢您的尝试,我将研究ALL
谓词,也许它会解决我的问题。我刚刚用正确的语句更新了我的答案。恐怕您误解了问题。我不想确定在A
,B
和C
在集合中(其他),但我正试图找到同时连接到A
,B
和C
的所有其他节点。例如,如果节点D
w