Neo4j公交线路应用建模

Neo4j公交线路应用建模,neo4j,graph-databases,Neo4j,Graph Databases,我的问题是,我有一个图,其中有很多节点代表公共汽车站。 我应该如何包括总线信息,例如节点之间可用的总线 我正在考虑在节点之间创建一个总线关系,该关系将包含两个节点之间所有总线的信息,以及一个标记两个站点之间距离的关系属性 buses[500A,182A],distance:500m buses[121B,542W,222A,111Z],distance:400m 比如A-------------------------------------------->B-------

我的问题是,我有一个图,其中有很多节点代表公共汽车站。 我应该如何包括总线信息,例如节点之间可用的总线

我正在考虑在节点之间创建一个总线关系,该关系将包含两个节点之间所有总线的信息,以及一个标记两个站点之间距离的关系属性

      buses[500A,182A],distance:500m     buses[121B,542W,222A,111Z],distance:400m
比如A-------------------------------------------->B-------------------------------------------->C

那么,我将如何找到从A到达M的一辆或多辆公交车(如果没有直接路径可用)

首先,我将找出路径(一个neo4j查询),如何从a到达M

说我的路是

buses[11A],distance:1000m    buses[11A],distance:250m   buses[13B,100A],distance:2000m
A------------------------------------------>L------------------------------------------>N------------------------------------------>M

问题是我如何通过编程检查直接到M的总线是否可用,或者我如何在两者之间交换总线

根据上面的场景,我可以从A到N到11A,然后从N到M,取13B或100A

我必须以编程的方式来做


我想检索两个站点之间的所有可能路径和路径的总距离以及总线信息。

由于可以在相同节点之间创建多个关系,我建议为每个总线创建一个关系。从你的例子来看:

A<-----------------B<-------------------------------C
   buses[180Q,171B]      buses[80A,43B,121S]
AA
等等

这样你就能做到

MATCH path=(start {id: '123'})-[:connects_to {bus: '180Q'}*1..10]-(end: {id: '321'})
UNWIND relationships(path) AS hop
WITH path, hop
WITH path, collect(DISTINCT hop.bus) AS busses
WHERE length(busses) <= 2
RETURN path
MATCH path=(开始{id:'123'})-[:将_连接到{bus:'180Q'}*1..10](结束:{id:'321'})
将关系(路径)作为跃点展开
用路径,跳跃
使用path,将(不同的hop.bus)收集为总线

WHERE length(busses)我尝试了很多密码查询,但是没有得到我想要的,公交换乘信息。到目前为止,我的问题是

MATCH (from:Stop { name:"A" }), (to:Stop { name: "S"}) , path = (from)-[:CONNECTED*]->(to)
unwind relationships(path) as hop
RETURN extract(n IN nodes(path)| n.name) AS Shortest_Route,collect(hop.Buses) as Buses,length(path) as Stop_Count,
reduce(distance = 0, r in relationships(path) | distance+r.distance) AS Shortest_Distance
ORDER BY Shortest_Distance ASC
LIMIT 1 .

我发现很难获得公交换乘信息。我想我必须通过编程来实现。它看起来并不复杂,但我正在考虑是否可以从cypher查询本身获得它。

您的模型需要更加图形化。也就是说,我认为不应该在站点节点与总线信息之间的关系上使用数组属性。相反,总线本身应该是具有关系的节点,以指示它们停在哪个站点。考虑下面的示例数据:

CREATE (a:Stop {name:'A'}),
       (b:Stop {name:'B'}),
       (c:Stop {name:'C'}),
       (d:Stop {name:'D'}),

       (a)-[:NEXT {distance:1}]->(b),
       (b)-[:NEXT {distance:2}]->(c),
       (c)-[:NEXT {distance:3}]->(d),

       (b1:Bus {id:1}),
       (b2:Bus {id:2}),
       (b3:Bus {id:3}),

       (b1)-[:STOPS_AT]->(a),
       (b1)-[:STOPS_AT]->(b),
       (b2)-[:STOPS_AT]->(a),
       (b2)-[:STOPS_AT]->(b),
       (b2)-[:STOPS_AT]->(c),
       (b3)-[:STOPS_AT]->(b),
       (b3)-[:STOPS_AT]->(c),
       (b3)-[:STOPS_AT]->(d);
现在的图表如下所示:

使用此模型,可以很容易地找到一个行程,该行程可以最大限度地减少换乘次数,并返回所有必要的换乘信息(如果适用)。例如,从A到D的所有最短行程(换乘次数最短):

MATCH (a:Stop {name:'A'}), (d:Stop {name:'D'})
MATCH p = allShortestPaths((a)-[:STOPS_AT*]-(d))
RETURN EXTRACT(x IN NODES(p) | CASE WHEN x:Stop THEN 'Stop ' + x.name
                                    WHEN x:Bus THEN 'Bus ' + x.id
                               ELSE '' END) AS itinerary
找到了三条路线,它们都有一个中转站:

Stop A, Bus 2, Stop C, Bus 3, Stop D
Stop A, Bus 1, Stop B, Bus 3, Stop D
Stop A, Bus 2, Stop B, Bus 3, Stop D
当然,您可以使用
EXTRACT()
函数以任何方式返回此信息

另一个例子。查找从A到C的行程:

MATCH (a:Stop {name:'A'}), (c:Stop {name:'C'})
MATCH p = allShortestPaths((a)-[:STOPS_AT*]-(c))
RETURN EXTRACT(x IN NODES(p) | CASE WHEN x:Stop THEN 'Stop ' + x.name
                                    WHEN x:Bus THEN 'Bus ' + x.id
                               ELSE '' END)
找到一条路线,但没有换乘:

Stop A, Bus 2, Stop C
如果这回答了你的问题,请告诉我

编辑:要获取距离,请执行以下操作:

MATCH (a:Stop {name:'A'}), (d:Stop {name:'D'})
MATCH route = allShortestPaths((a)-[:STOPS_AT*]-(d)),
      stops = (a)-[:NEXT*]->(d)
RETURN EXTRACT(x IN NODES(route) | CASE WHEN x:Stop THEN 'Stop ' + x.name
                                        WHEN x:Bus THEN 'Bus ' + x.id
                                   ELSE '' END) AS itinerary,
       REDUCE(d = 0, x IN RELATIONSHIPS(stops) | d + x.distance) AS distance


                           itinerary  distance
Stop A, Bus 1, Stop B, Bus 3, Stop D         6
Stop A, Bus 2, Stop B, Bus 3, Stop D         6
Stop A, Bus 2, Stop C, Bus 3, Stop D         6

我知道我可以在节点之间创建多个关系。但是@Brian的问题是,即使我通过cypher查询得到节点之间的最短路径,我仍然必须通过编程检查cypher查询返回的路径,以表示车站的公交换乘。查询并没有告诉我在哪里换乘,它只给了我从A到B的最短路径,以及到达目的地的巴士详细信息。我希望我能告诉你我的问题。啊,我想也许我能理解。你想找到包括换乘在内的最短路线吗(在一站下车,然后换另一条路线)?是的@Brian这就是我要找的。有什么办法吗?所以我刚刚用一个我根本没有尝试过的问题更新了答案,我不确定这个问题是否可行,但我怀疑如果你玩一下这个问题的话,也许可以。此外,根据您想回答的问题类型,您可能需要考虑编写/查找非托管扩展名Tanks@Brian我将处理查询,看起来Neo4j中有一些内容可供我查询。谢谢Nicole,这就是我一直在寻找的。我将distance属性添加到站点之间的下一个关系中。我尝试此查询以获取每种可能方式的总距离。但它返回null<代码>匹配(a:Stop{name:'a'}),(c:Stop{name:'c'})匹配p=allshortestpath((a)-[:STOPS_AT*]-(c))返回提取(节点中的x(p)|当x:Stop然后'Stop'+x.name当x:Bus然后'Bus'+x.id ELSE'结束时,减少(距离=0,关系中的r)|距离+r.distance)作为距离
。你能解释一下这个查询是如何在内部工作的吗?我不知道距离是一个因素-你能编辑你的问题以包含这个因素吗?您的上述查询返回null,因为您匹配的是
站点关系,而不是
下一个
关系。是否要最小化距离或换乘次数?我想获得所有可能的路线,其中包含公交换乘信息以及每条路径的总数据间隔。
MATCH (a:Stop {name:'A'}), (d:Stop {name:'D'})
MATCH route = allShortestPaths((a)-[:STOPS_AT*]-(d)),
      stops = (a)-[:NEXT*]->(d)
RETURN EXTRACT(x IN NODES(route) | CASE WHEN x:Stop THEN 'Stop ' + x.name
                                        WHEN x:Bus THEN 'Bus ' + x.id
                                   ELSE '' END) AS itinerary,
       REDUCE(d = 0, x IN RELATIONSHIPS(stops) | d + x.distance) AS distance


                           itinerary  distance
Stop A, Bus 1, Stop B, Bus 3, Stop D         6
Stop A, Bus 2, Stop B, Bus 3, Stop D         6
Stop A, Bus 2, Stop C, Bus 3, Stop D         6