【问题标题】:Shortest paths without supernodes in Neo4jNeo4j 中没有超节点的最短路径
【发布时间】:2017-08-20 11:56:55
【问题描述】:

我在 Neo 中有一个包含 5 亿个节点和边的图。我想找到避免超级节点的 2 个节点之间的最短路径(即使它比上面有超级节点的路径长)。

以下查询适用于较小的图表,但对于我正在处理的大小的图表永远不会完成:

MATCH (n:Node { id:'123'}),(m:Node { id:'234' }), p = shortestPath((n)-[*..6]-(m)) 
WHERE NONE(x IN NODES(p) WHERE size((x)--())>1000)
RETURN p

如果我删除 WHERE 子句,它会非常快。通常是亚秒级。

如何加快速度?预先计算节点度数和索引它们有帮助吗?我是否应该求助于复制除了与超级节点相邻的边缘之外的所有边缘,给它们一个新标签并将它们用于我的 shortestPath 查询而不使用 WHERE 子句?还有其他建议吗?

【问题讨论】:

  • 去掉标签会怎样? WHERE NONE(x IN NODES(p) WHERE size((x)--()) > 1000)
  • 好点。抱歉,我实际上是在 WHERE 子句中没有标签的情况下测试它。对于第一个标签,它会出错。第二个标签似乎没有任何区别。让我更新我的问题以删除标签。作为参考,它最初看起来像这样: WHERE NONE(x:Node IN NODES(p) WHERE size((x:Node)--())>1000)

标签: graph neo4j cypher shortest-path


【解决方案1】:

据我所知,当 WHERE ALL 仅包含关系(不包含节点)时,Neo4j 最短路径实现会修剪路径。如果它无法修剪查询,它会找到所有路径然后过滤它们(慢)。

正如 Martin 所说,您可以添加标签:

MATCH (x:Node)
WHERE size((x)--())>1000
SET n:Supernode

然后通过边询问节点的标签:

MATCH p = shortestPath((n:Node { id:'1'})-[*..6]-(m:Node { id:'2' })) 
WHERE ALL( rel IN relationships(p) WHERE not (startNode(rel):Supernode or endNode(rel):Supernode))
RETURN p

这将允许 Neo4j 使用优化的双向广度优先(快速)查询。

更多阅读内容: https://neo4j.com/docs/developer-manual/current/cypher/execution-plans/shortestpath-planning/

【讨论】:

    【解决方案2】:

    您也可以尝试为超级节点添加标签:

    MATCH (x:Node)
    WHERE size((x)--())>1000
    SET n:Supernode
    

    这是否会在您的数据上运行并完成?你有多少个超级节点和普通节点?

    那就试试吧:

    MATCH (n:Node { id:'123'}),(m:Node { id:'234' })
    WITH n, m
    MATCH p = shortestPath((n)-[*..6]-(m))
    WHERE NONE(x IN NODES(p) WHERE (x:Supernode))
    RETURN p
    

    我想标签检查更快。

    【讨论】:

    • 谢谢。这并不能解决问题,但它很有用。所以我有将近0.5G的节点。我能够在 9 m 内运行您的第一个查询来标记超级节点。其中有 525 个(即学位 > 1k)。不幸的是,如果节点 n 和 m 之间存在超级节点,则第二个查询仍然需要很长时间。据我所知,如果这些节点附近没有超级节点,那速度非常快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-31
    • 2016-05-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多