我正在寻找一个快速的Cypher语句,它返回一组已知节点之间的所有关系(我有他们的Neo4j ID),这样我就可以组合该特定节点集的子图。我正在一个名为label
的标签内工作,该标签在这些节点之间有大约50K节点和800K边缘。
我有几种工作方法,但是对于我的应用程序来说,没有一种方法足够快,即使在小的设置大小(少于1000个节点)时也是如此。
例如,以下语句可以解决问题:
MATCH (u:label)-[r]->(v:label)
WHERE (ID(u) IN {ids}) AND (ID(v) IN {ids})
RETURN collect(r)
其中{ids}
是作为Py2Neo cypher.execute(statement, parameters)
方法的参数给出的数字Neo4j ID的列表。问题是一组838个节点需要大约34秒,这会返回它们之间的所有19K关系。我意识到图形有点密集,但每返回1000条边需要1.76秒。我不认为这是可以接受的。
如果我改用START子句(如下所示),时间实际上会更糟糕。
START u=node({ids}), v=node({ids})
MATCH (u:label)-[r]->(v:label)
RETURN collect(r)
我发现了很多类似的问题/答案,但在某些方面它们都不尽如人意。有没有更好的声明来做这个,甚至更好的图形模式,以便它可以扩展到数千个节点的集合?
感谢您的快速回复。首先,要将当前查询作为输入(len(ids)=528
)运行528个节点,需要 32.1秒,查询计划如下。
NodeByIdSeek: 528 hits
Filter : 528 hits
Expand(All) : 73,773 hits
Filter : 73,245 hits
Projection : 0 hits
Filter : 0 hits
Brian Underwood 的查询,输入相同, 27.8秒。查询计划是相同的,除了最后两个步骤(投影和过滤器),其查询不存在。然而db命中总和是相同的。
Michael Hunger 的查询 26.9秒,查询计划与Brian的查询相同。
我在实验之间重新启动服务器以避免缓存效果(这可能是一种更聪明的方法)。我也直接从网络界面查询,通过我的代码和我正在使用的库中可能存在的瓶颈。
Bottomline,Neo4j看起来很聪明,可以优化我的查询,但即使使用相当小的集合,它仍然很慢。有什么建议吗?
答案 0 :(得分:1)
我认为问题在于查询正在使用笛卡尔积来获取838节点的所有组合,因此您最终搜索838 * 838 = 702,244个组合。
我很好奇这将如何表现:
MATCH (u:label)-[r]->(v:label)
WHERE (ID(u) IN {ids})
WITH r, v
WHERE (ID(v) IN {ids})
RETURN collect(r)
另外,为什么最后collect
?
答案 1 :(得分:0)
你的id列表有多大?
试试这个:
MATCH (u) WHERE ID(u) IN {ids}
WITH u
MATCH (v)-[r]->(v)
WHERE ID(v) IN {ids}
RETURN count(*)
MATCH (u) WHERE (ID(u) IN {ids})
WITH u
MATCH (v)-[r]->(v)
WHERE ID(v) IN {ids}
RETURN r
还可以尝试通过在PROFILE
前面添加查询来创建查询计划,然后查看费用的位置。