我正在为几个城市之间的传输创建简单的图表数据库。我的结构是:
我需要找到从城市A到城市C的路线,但我没有直接停止连接,但它们通过城市B连接。请picture请新增用户,我无法发布图像进行提问。
如何通过STOP 1从A市区获得路由器然后将RIDE 1连接到STOP 2 STOP 2由同一城市B连接到STOP3,最后从STOP3通过RIDE2连接到STOP4(城市C)?
谢谢。
更新
Vince的解决方案没问题,但是我需要设置过滤器来停止节点的出发时间,比如
MATCH p=shortestPath((a:City {name:'A'})-[*{departuretime>xxx}]-(c:City {name:'C'})) RETURN p
是否可以在没有迭代的情况下进行所有匹配集合?因为它要慢。
答案 0 :(得分:2)
如果您只是在两个节点之间寻找单个路由,则此Cypher查询将返回两个City节点A和C之间的最短路径。
MATCH p=shortestPath((a:City {name:'A'})-[*]-(c:City {name:'C'})) RETURN p
通常,如果图表中有很多潜在路径,则应适当限制搜索深度:
MATCH p=shortestPath((a:City {name:'A'})-[*..4]-(c:City {name:'C'})) RETURN p
如果要返回所有可能的路径,可以省略shortestPath子句:
MATCH p=(a:City {name:'A'})-[*]-(c:City) {name:'C'}) RETURN p
同样的警告适用。有关详细信息,请参阅Neo4j documentation
<强>更新强> 在您的后续评论之后。
我不确定时间属性的确切目的是什么,但似乎您实际上想要根据一些最小时间成本创建两个节点之间的最短加权路径。这当然与 shortestPath 不同,因为它最大限度地减少了遍历的边数,而不是这些边的成本。
您通常会对边缘而不是节点上的遍历成本进行建模,但您的图形仅在STOP节点上有时间(而不是例如在RIDE边缘或CITY节点上)。要在此处进行最短加权路径查询,我们还需要将时间建模为所有节点和边上的属性。如果进行此更改,并将所有节点/边缘的值设置为0,那么以下Cypher查询就会执行我认为您需要的内容。
MATCH p=(a:City {name: 'A'})-[*]-(c:City {name:'C'})
RETURN p AS shortestPath,
reduce(time=0, n in nodes(p) | time + n.time) AS m,
reduce(time=0, r in relationships(p) | time + r.time) as n
ORDER BY m + n ASC
LIMIT 1
在您的示例图表中,这会产生A和C之间的最低成本路径:
(A)->(STOP1)-(STOP2)->(B)->(STOP5)->(STOP6)->(C)
最低时间成本为230.
这条路径包括两个你指定为“坏”的站点,虽然我不太明白为什么它们很糟糕,因为它们的遍历成本低于其他非“坏”的站点。
或者,使用Dijkstra
这个简单的Cypher可能无法在密集连接的图上表现出色。如果发现性能有问题,则应使用源节点的REST API和路径端点,并使用Dijkstra算法请求到目标节点的最短加权路径。详情here
答案 1 :(得分:1)
好的,如果要求通过图表找到每个站点的出发时间不早于前一站点的出发时间的路径,这应该有效:
MATCH p=(:City {name:'A'})-[*]-(:City {name:'C'})
MATCH (a:Stop) where a in nodes(p)
MATCH (b:Stop) where b in nodes(p)
WITH p, a, b order by b.time
WITH p as ps, collect(distinct a) as as, collect(distinct b) as bs
WHERE as = bs
WITH ps, last(as).time - head(as).time as elapsed
RETURN ps, elapsed ORDER BY elapsed ASC
此查询通过匹配每个可能的路径,然后两次收集每个匹配路径上的所有停靠点来工作。其中一个停靠点是按出发时间排序,而另一个不是。只有两个集合相等(即数字和顺序)才是结果的结果。此步骤将逐出无效路由。最后,路径本身按第一个和最后一个停靠点之间的最短经过时间排序,因此最快的路径是列表中的第一个。
有关表现等的正常警告适用:)