2016-09-22 70 views
0

所以我试图在包含stop和route节点的neo4j图中获得间接路由。在neo4j中获取间接路由,考虑它们在路由中的出现顺序

这是我的关系数据库的ER图。

enter image description here

我的模型由具有各车站的名称(图中的蓝色节点)节点停止节点。

我有多个路径与停止节点有关系(STOPS_AT)。这些关系指向公共汽车在遵循特定路线时所进行的各种停靠。

停止关系具有以下属性。

fare_bt_stops - 它在此站点和上一站点之间有行程票价。 订单 - 巴士在站点停靠的顺序。原产地为0

这就是我的STOPS_AT关系外观。

enter image description here

enter image description here

所以去C A之间的最短距离我运行此查询来获取其中给出输出[Stop 12, Route 4, Stop 13, Route 5, Stop 14] A和C.

MATCH (a:Stop {name:'A'}), (d:Stop {name:'C'}) 
MATCH p = allShortestPaths((a)-[:STOPS_AT*..12]-(d)) 
RETURN EXTRACT(x IN NODES(p) | CASE WHEN x:Stop THEN 'Stop ' + x.name 
            WHEN x:Route THEN 'Route ' + x.name 
            ELSE '' END) AS itinerary 

之间的路由

但是,如何查询此模型以获得最少票价的路径。我已经看到了其他的例子,但在这些例子中,节点是直接连接的,而在我的这些例子中,它们通过Route节点连接。

加上我怎么根据stop_order财产例如路由验证路线A to B停在A,然后再基于B而布线C to B在C停止第一,然后是B所以不应该有任何的方式从A到达到C但是这个查询并没有处理这个特定的情况。所以现在我正在处理我的代码,我认为这不是最好的方式。

我被困在这个过去两天,所以将不胜感激任何帮助,我可以得到。

+0

您应该在问题中描述您的模型,而不是链接到GrapheneDB实例(似乎不再存在)。这样它在未来仍然有用。 –

回答

2

在我看来,你太依赖关系数据库中的表格建模了。您正在使用Neo4j,因此您将不得不考虑将表格模型转换为模型并在图形模型中实现丰富查询的最佳方法。在这种转换中,关系数据库中的许多管道工作将不再需要,而且一开始就很难识别和查看。你可能要改造这个

一种方法是删除您的中间节点,而不是简单地使用每个站之间的关系

因此,举例来说,如果我们将其归类的路线作为一个路径:与路由关系相同的号码,你可以很容易地创建你的路线。它可能是这样的模型:

(:Bus{ID:1, color:"green", number:"5"})-[:AssignedTo]->(:BusRoute{number:1}, departureTime:xxx})-[:Start]->(:Stop{name:"a"})-[:Route{number:1, fare:"10", duration:"20"]->(:Stop{name:"b"})-[:Route{number:1, fare:"20", duration:"30", finalStop:true}]->(:Stop{name:"d"}) 

(:Bus{ID:2, color:"red", number:"7"})-[:AssignedTo]->(:BusRoute{number:2}, departureTime:xxx})-[:Start]->(:Stop{name:"d"})-[:Route{number:2, fare:"10", duration:"20"]->(:Stop{name:"c"})-[:Route{number:2 fare:"20", duration:"30"}]->(:Stop{name:"b"}) ... 

这使得你的路线清晰明了。还要注意:分配给该路线的公共汽车是明确的,并且很容易改变,因为公共汽车与路线的关联在一个地方。

查找路由1的路由,例如将使用类似的查询:

MATCH (bus:Bus)-[:AssignedTo]->(busRoute:BusRoute)-[:Start]->(first:Stop) 
WHERE busRoute.number = 1 
WITH bus, busRoute, first 
MATCH (first)-[r:Route*]->(:Stop) 
WHERE ALL(route in r | route.number = br.number) 
AND LAST(r).finalStop = true 
RETURN bus, busRoute, NODES(r) as stops 

以及从任何阻止任何其他站的最短路径查询,用票价为重,你可以使用Cypher自己完成此操作,或者您可以使用APOC过程调用为您执行此操作。

首先,简单的方法。如果你安装了APOC Procedures library,可以让这个查询:

MATCH (here:Stop), (destination:Stop) 
WHERE here.name = xxx AND destination.name = xxx 
WITH here, destination 
CALL apoc.algo.dijkstra(here, destination, 'Route>', 'fare') YIELD path, weight 
RETURN RELS(path) as rides, weight as cost 

如果你想自己做,你可以做这样的(添加一个理智的限制你的变量路径深度)

MATCH (here:Stop), (destination:Stop) 
WHERE here.name = xxx AND destination.name = xxx 
WITH here, destination 
MATCH (here)-[rides:Route*..12]->(destination) 
WITH rides, REDUCE(cost = 0, ride in rides | cost + ride.fare) AS cost 
ORDER BY cost ASC LIMIT 1 
RETURN rides, cost 
+0

我爱你。说真的,我知道有一个更好的方法来做到这一点,但却无法找到一个,因为我正在以一种更相关的方式去做事情。你的解决方案让你很有道理,你不知道。我现在试着设计一个,然后我会告诉你结果。非常感谢你:) – Angersmash

+0

很高兴帮助!将您的思维从关系变为图形有几个障碍,这都是整个过程的一部分。您还倾向于在如何在图形中对事物建模时拥有更多自由度,因此不同的主要用例可能需要对模型进行一些更改。希望它适合你,如果遇到任何麻烦,很乐意提供帮助。 – InverseFalcon

0

问题中模型的信息不足以回答票价部分。

关于订单的问题,如果Route有一个方向,所以要它与Stops关系:

(c:Stop {name: 'C'})-[:STOPS_AT]->(c_to_b:Route)-[:STOPS_AT]->(b:Stop {name: 'B'}) 

除关系型是没有意义的,现在,你也可以使用2种不同类型:

(c:Stop {name: 'C'})-[:IS_ORIGIN]->(c_to_b:Route)-[:IS_DESTINATION]->(b:Stop {name: 'B'}) 

而现在,如果你在同一个方向遵循两种类型,你按照实际路线(如果存在的话):

MATCH p = allShortestPaths((a)-[:IS_ORIGIN|IS_DESTINATION*..12]->(d)) 
+0

嘿,在那里,我很抱歉,我没有真正关注你想说的话。你能否详细说明你的答案。我应该以不同的方式建模吗我仍然困惑于如何在两条路线之间分享站点,我只能想到我现在的模型。正如你可以使用多条路线从A到B一样,我应该在A到B之间创建一个直接的边,并且边有一个在这两个站之间的路径数组?我还添加了我的关系图。 – Angersmash