【问题标题】:Neo4j shortest path with rels in both directionsNeo4j 双向 rels 的最短路径
【发布时间】:2014-03-17 14:13:04
【问题描述】:

我用函数设置了一个图表...

create (a:station {name:"a"}),
(b:station {name:"b"}),
(c:station {name:"c"}),
(d:station {name:"d"}),
(e:station {name:"e"}),
(f:station {name:"f"}),
(a)-[:CONNECTS_TO {time:8}]->(b),
(a)-[:CONNECTS_TO {time:4}]->(c),
(a)-[:CONNECTS_TO {time:10}]->(d),
(b)-[:CONNECTS_TO {time:3}]->(c),
(b)-[:CONNECTS_TO {time:9}]->(e),
(c)-[:CONNECTS_TO {time:40}]->(f),
(d)-[:CONNECTS_TO {time:5}]->(e),
(e)-[:CONNECTS_TO {time:3}]->(f)

并使用函数

START startStation=node:node_auto_index(name = "a"), endStation=node:node_auto_index(name = "f")
MATCH p =(startStation)-[r*]->(endStation)
WITH extract(x IN rels(p)| x.time) AS Times, length(p) AS `Number of Stops`, reduce(totalTime = 0, x IN rels(p)| totalTime + x.time) AS `Total Time`, extract(x IN nodes(p)| x.name) AS Route
RETURN Route, Times, `Total Time`, `Number of Stops`
ORDER BY `Total Time`

它会返回结果...

+-------------------------------------------------------------+
| Route             | Times    | Total Time | Number of Stops |
+-------------------------------------------------------------+
| ["a","d","e","f"] | [10,5,3] | 18         | 3               |
| ["a","b","e","f"] | [8,9,3]  | 20         | 3               |
| ["a","c","f"]     | [4,40]   | 44         | 2               |
| ["a","b","c","f"] | [8,3,40] | 51         | 3               |
+-------------------------------------------------------------+

这很好,除了因为它是一个有向图并且没有来自c -> b 的路径,它不会返回(例如)[a, c, b, e, f],这是一个长度为 4 的有效路径。

所以,如果我添加反向路径...

MATCH (START)-[r:CONNECTS_TO]->(END )
CREATE UNIQUE (START)<-[:CONNECTS_TO { time:r.time }]-(END )

然后再次运行查询,我得到...(路径长度为 1..4)...

+---------------------------------------------------------------------+
| Route                 | Times        | Total Time | Number of Stops |
+---------------------------------------------------------------------+
| ["a","d","e","f"]     | [10,5,3]     | 18         | 3               |
| ["a","c","b","e","f"] | [4,3,9,3]    | 19         | 4               |
| ["a","b","e","f"]     | [8,9,3]      | 20         | 3               |
| ["a","c","f"]         | [4,40]       | 44         | 2               |
| ["a","c","b","c","f"] | [4,3,3,40]   | 50         | 4               |
| ["a","c","f","e","f"] | [4,40,3,3]   | 50         | 4               |
| ["a","b","c","f"]     | [8,3,40]     | 51         | 3               |
| ["a","b","a","c","f"] | [8,8,4,40]   | 60         | 4               |
| ["a","d","a","c","f"] | [10,10,4,40] | 64         | 4               |
+---------------------------------------------------------------------+

这确实包括路径[a, c, b, e, f],但也包括使用c 两次的[a, c, b, c, f] 和使用f(目的地?!)两次的[a, c, f, e, f]

有没有办法过滤路径,使每条路径只包含一次相同的节点?

【问题讨论】:

    标签: graph neo4j shortest-path


    【解决方案1】:

    您可以事后进行过滤,但这可能不是最快的。

    类似这样的:

    START startStation=node:node_auto_index(name = "a"), endStation=node:node_auto_index(name = "f")
    MATCH p = (startStation)-[r*..4]->(endStation)
    
    WHERE length(reduce (a=[startStation], n IN nodes(p) | CASE WHEN n IN a THEN a ELSE a + n END)) = length(nodes(p))
    
    WITH extract(x IN rels(p)| x.time) AS Times, length(p) AS `Number of Stops`, reduce(totalTime = 0, x IN rels(p)| totalTime + x.time) AS `Total Time`, extract(x IN nodes(p)| x.name) AS Route
    RETURN Route, Times, `Total Time`, `Number of Stops`
    ORDER BY `Total Time`
    

    我创建了一个 GraphGist,其中包含您的问题和答案作为可执行的实时文档。

    请看这里:Neo4j shortest path with rels in both directions

    【讨论】:

    • 非常感谢!这正是我想要的,谢谢:D BTW ...来自 Neo4j 手册docs.neo4j.org/chunked/stable/rest-api-graph-algos.html REST API 方法似乎具有 Dijkstra 算法最短路径功能。这在 Cypher 中也可用吗?
    • 不幸的是,Cypher 中还没有 Dijkstra。也是有计划的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多