我有一个标签图,它们彼此相关。我的目标是创建一个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
,然后搜索与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;
但是当输入标签的数量增加时(在这种情况下只有3个输入标签:A
,B
,C
),它的运行速度非常缓慢。
那么有没有办法在一个查询中创建它,类似于我的第一次尝试?
答案 0 :(得分: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;
other
)“相关”(最多2步)的所有代码(t
)。other
收集不同的 t
节点。在此示例中,我们最终得到3个others
个集合 - 每个t
有1个集合。需要注意的重要一点是查询结果是每个 others
集合的交集。others
个集合收集到一个coll
集合中。others
集合的交集,因此查询将遍历第一个others
集合中的节点,并提取其余others
中的节点。集合。并且,由于每个others
集合已包含不同的节点,因此结果还必须具有不同的节点。此外,如果您有很多标签,可以通过以下方式加快上述查询:
:Tag(name)
,然后在查询中指定使用该索引 - 在MATCH
和WHERE
子句之间插入以下子句。目前,Cypher引擎不会自动使用此特定查询的索引。
USING INDEX t:Tag(name)
答案 1 :(得分:1)
这是另一种选择:
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
首先匹配所有可访问的标记。如果使用shortestPath,则从长度为n的列表中的所有标记可到达的所有标记必须已匹配n次。如果您按照该标准进行过滤(当前n次),则可以使用不同的标记来检索所需的标记。
答案 2 :(得分:0)
这个怎么样:
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都是其中的一部分。