更好的方法从neo4j图中的路径中删除循环

时间:2015-04-30 10:17:30

标签: neo4j cypher

我正在使用neo4j图形数据库版本2.1.7。数据简要介绍: 200万个节点有6种不同类型的节点,500万个关系只有5种不同类型的关系,大多数是连接图,但包含一些孤立的子图。

在解析路径时,我会在路径中获得循环。为了限制它,我使用了以下共享的解决方案: Returning only simple paths in Neo4j Cypher query

这是查询,我正在使用:

aamodel.headerData.collection.remove(model);

上面的查询解决了我的需求但是不具成本效益,并且如果为巨大的子图运行则继续运行。我使用'Profile'命令来改善我开始时的查询性能。但是,现在卡在这一点上。性能有所改善,但不是我对neo4j的期望:(

2 个答案:

答案 0 :(得分:2)

我不知道我有解决方案,但我有很多建议。有些可能会加快速度,有些可能只是让查询更容易阅读。

首先,不要将exists ((c)-[:rel5]->(b))放在WHERE中,我相信你可以将它放在你的MATCH中:

MATCH path = n-[:rel1|rel2|rel3|rel4*0..]->(c:nodeA)-[:rel5*0..1]->(b:nodeA), (c)-[:rel5]->(b)

我认为您不需要exists关键字。我想你可以说,例如,(NOT (b)-[:rel1|rel2|rel3|rel4]->(:nodeA))

我还建议考虑WITH clause潜在的性能改进。

关于您的可变路径的一些注意事项:在*0..中,0表示您可能正在寻找自我引用。这可能是也可能不是你想要的。此外,将变量路径保持开放状态通常会导致性能问题(正如我认为您所看到的那样)。如果你可以限制它可能有帮助。

此外,如果你升级到2.2.1,2.2.x系列有许多内置的性能改进,但你也可以在控制台中获得视觉PROFILE和一个新的{{1这两个配置文件在运行它之后会告诉你查询的真实性能。

我还要考虑的一件事是,我认为你没有达到Neo4j的性能界限,但也许你可能会遇到Cypher的某些界限。如果是这样,我可能会建议您使用Neo4j提供的Java API进行查询,以获得更好的性能和更多的控制。这可以是通过嵌入数据库(如果您使用的是与JVM兼容的语言)或者编写unmanaged extension,它允许您在java中进行自己的查询,但是从服务器提供自定义REST API

答案 1 :(得分:1)

如上所述,Brian对我的查询进行了几次调整。并发现查询响应时间有所改善。现在,与我原始查询相比,执行时间几乎占用了20%,与查询执行期间之前共享的查询相比,当前查询的db命中率降低了近60%。 PFB更新的查询:

MATCH (n:nodeA{key:905728}) 
MATCH path = n-[:rel1|rel2|rel3|rel4*1..]->(c:nodeA)-[:rel5*0..1]->(b:nodeA) 
WHERE ALL(a in nodes(path) where 1=length (filter (m in nodes(path) where m=a))) 
and (length(path) > 0) 
and ((exists ((c)-[:rel5]->(b)) and (not ((c)-[:rel1|rel2|rel3|rel4]->()) OR ANY (x in nodes(path) where (c)-[]->(x))))
    OR (not exists ((c)-[:rel5]->()) and (not ((c)-[:rel1|rel2|rel3|rel4]->()) OR ANY (x in nodes(path) where (c)-[]->(x))))) 
RETURN distinct EXTRACT (rp in Rels(path)| type(rp)), EXTRACT (p in NODES(path)| p.key);

当从* 1 ..到* 1..15的路径上限时,观察到了显着的改善。此外,从查询中删除了一个过滤器,这也需要更长的时间。 但是,当查询具有超过18-20个深度的关系的节点时,查询响应时间增加。

我建议经常使用profile命令查找查询中的痛点。这将有助于您更快地解决问题。 谢谢Brian。