Neo4j Cypher找到两个不相交的节点

时间:2017-04-22 21:31:50

标签: neo4j cypher anormcypher

我使用Neo4j尝试查找未连接到特定节点的任何节点" a"。我到目前为止的查询是:

MATCH p = shortestPath((a:Node {id:"123"})-[*]-(b:Node))
WHERE p IS NULL
RETURN b.id as b

因此它试图找到a和b之间的最短路径。如果它没有找到路径,则它返回该节点的id。但是,这会导致我的查询运行几分钟,然后在内存不足时崩溃。我想知道这种方法是否会起作用,是否有更有效的方法?任何帮助将不胜感激!

编辑:

MATCH (a:Node {id:"123"})-[*]-(b:Node),
(c:Node)
WITH collect(b) as col, a, b, c
WHERE a <> b AND NOT c IN col
RETURN c.id 

所以col(collect(b))包含连接到a的每个节点,因此如果c不在col中那么c是不是连接到?

1 个答案:

答案 0 :(得分:1)

首先,你给这个MATCH一个不可能的谓词来实现,所以它永远找不到最短的路径。

WHERE子句与MATCH,OPTIONAL MATCH和WITH子句相关联,因此您的查询要求路径不存在的最短路径。这将永远不会返回任何东西。

此外,shortestPath将从您想要连接的节点开始,因此无法找到与其无关的节点。

可能最简单的方法是匹配连接到您所讨论的节点的所有节点,然后匹配所有:节点检查连接集中的那些节点。这意味着您不必从数据库中的每个节点执行shortestPath,只需对集合中的成员资格进行检查。

你需要APOC Procedures,因为它有最快的方法匹配子图中的节点。

MATCH (a:Node {id:"123"})
CALL apoc.path.subgraphNodes(a, {}) YIELD node
WITH collect(node) as subgraph
MATCH (b:Node)
WHERE NOT b in subgraph
RETURN b.id as b

修改

您编辑的查询可能会爆炸,这会生成一个巨大的结果集(该查询将构建一个结果集,该结果集可以通过笛卡尔积中的唯一路径从您的起始节点到达每个节点:节点)

相反,请逐步进行,收集不同的节点(因为否则您将获得可通过不同路径到达的相同节点的倍数),然后只有在您收集后才能开始匹配对于列表中没有的节点。

MATCH (:Node {id:"123"})-[*0..]-(b:Node)
WITH collect(DISTINCT b) as col
MATCH (a:Node)
WHERE NOT a IN col
RETURN a.id