首页 文章

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

提问于
浏览
4

我正在使用neo4j图形数据库版本2.1.7 . 关于数据的简要细节:具有6种不同类型节点的200万个节点,仅具有5种不同类型关系的500万个关系,并且主要是连接图,但是包含一些孤立的子图 .

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

这是查询,我正在使用:

MATCH (n:nodeA{key:905728}) 
MATCH path = n-[:rel1|rel2|rel3|rel4*0..]->(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(EXTRACT (p in NODES(path)| p.key)) > 1) 
and ((exists ((c)-[:rel5]->(b)) and (not exists((b)-[:rel1|rel2|rel3|rel4]->(:nodeA)) OR ANY (x in nodes(path) where (b)-[]->(x))))
    OR (not exists ((c)-[:rel5]->()) and (not exists ((c)-[:rel1|rel2|rel3|rel4]->(:nodeA)) 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);

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

2 回答

  • 1

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

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

    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 和一个新的 EXPLAIN 命令,这两个命令都可以告诉您真实的运行后查询的性能 .

    还有一点需要考虑的是,我没有重新达到Neo4j的性能界限,但是,或许,您可以使用与JVM兼容的语言或编写unmanaged extension,它允许您在java中进行自己的查询但提供自定义REST API从服务器

  • 2

    如上所述,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 .

相关问题