给定Neo4j中的一个有向图(但可能有周期),我该如何使用Cypher检索特定节点可到达的所有节点?
(另外:如果我的图形有200万个节点,并且扩展到4800万个节点,我希望这样的查询能花费多长时间?例如,粗略的量规可以做到不到一分钟,几分钟,一个小时)
答案 0 :(得分:0)
看看here,其中将一种算法用于社区检测。
您可以使用类似的
match (n:Movie {title:"The Matrix"})-[r*1..50]-(m) return distinct id(m)
但这很慢(在具有60k节点的Neo4j movie dataset上进行的测试,上面的命令已经运行了10分钟以上。当您拥有一个由数百万个节点组成的数据集时,内存使用可能会成为一个问题。那也取决于您的数据集如何连接,例如关系的nr。
答案 1 :(得分:0)
Cypher的唯一性行为是关系必须在每个路径上都是唯一的(每个关系只能在每个路径上遍历一次),但这对于这类用例(目标是查找不同的节点)而言并不高效。一个节点总共只能访问一次(跨越所有路径,而不是每个路径)。
path expander procedures中有一些APOC Procedures library是针对这些用例的。
如果您尝试从起始节点查找所有可到达的节点,并沿任一方向遍历关系,则可以像电影图一样使用apoc.path.subgraphNodes()
,例如:
MATCH (n:Movie {title:"The Matrix"})
CALL apoc.path.subgraphNodes(n, {}) YIELD node
RETURN node
如果您只希望可到达的节点沿着特定的方向(例如传出)进行操作,则可以使用RelationshipFilter进行指定。如果很重要,您也可以添加类型,但是如果我们仅希望通过任何传出关系可访问,查询将类似于:
MATCH (n:Movie {title:"The Matrix"})
CALL apoc.path.subgraphNodes(n, {relationshipFilter:'>'}) YIELD node
RETURN node
在任何一种情况下,这些方法都比单独使用Cypher更好,尤其是在任何中等连通的图中,因为对于每个可达节点都只会考虑一条路径(将修剪掉已访问节点的替代路径,从而切断遍历遍历期间可能探索的路径,这非常有效,因为我们不在乎此用例的这些替代路径。