Neo4j总线路由应用程序建模

时间:2014-12-27 05:48:55

标签: neo4j graph-databases

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

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

      buses[500A,182A],distance:500m     buses[121B,542W,222A,111Z],distance:400m

喜欢A --------------------------------------------- ---------->乙------------------------------------- ----------------------&以及c

那么如何找到总线或公共汽车(如果没有可用的直达路径)从A到达M?

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

说我的路径是

buses[11A],distance:1000m    buses[11A],distance:250m   buses[13B,100A],distance:2000m

一个-----------------------------------------> L-- ---------------------------------将N -------------- -----------------------------> M

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

根据上述情况,我可以通过13B或100A从A到N到11A,然后从N到M.

我必须以编程方式执行此操作。

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

3 个答案:

答案 0 :(得分:13)

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

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);

图表现在看起来像这样:

model

使用此模型,可以轻松找到最小化转移次数的行程,并返回所有必要的转移信息(如果适用)。例如,从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

答案 1 :(得分:0)

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

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

您可以执行以下操作:

<somehow MATCH on A and B>
CREATE B-[:connects_to {bus: '180Q'}]->A
CREATE B-[:connects_to {bus: '171B'}]->A

依旧......

你可以这样做

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

老实说,我从来没有同时使用过关系属性匹配作为可变长度规范,但我想它会起作用

答案 2 :(得分:0)

我尝试了很多cypher查询,但无法得到我要找的东西,总线交换信息。到现在为止,我的查询是。

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 .

我发现很难得到总线交换信息。我想我必须以编程方式进行。它看起来并不复杂,但我在想如果我可以从密码查询中获取它。