How to find the shortest path with the minimum number of hops in Neo4j?

*爱你&永不变心* 提交于 2019-12-10 15:16:57

问题


Im modeling a graph where nodes are places and edges indicate that you can go from one place to another.

This is to have all routes that you can take from a place to another, and you can go from a place to another by different routes, so I want a query that returns me the shortest path with the minimum route changes.

For example, I want to go from A to D, I have two possible paths:

(place {name: "A"})-[:FOLLOWS{route:""R1}]->(place{name: "B" })-[:FOLLOWS{route:""R4}]->(place{name:"C"})-[:FOLLOWS{route:""R2}]->(place{name:"D"})

(place {name: "A"})-[:FOLLOWS{route:""R1}]->(place{name: "B" })-[:FOLLOWS{route:""R1}]->(place{name:"F"})-[:FOLLOWS{route:""R2}]->(place{name:"D"})

In the previous two path, both are the same size, but I would like to get the second one, which is the one who has the minimum route changes.

Thank you.


回答1:


I think this will meet your needs. It finds all of the shortest paths. Then it processes each one to count the number of route changes. It then orders the result set by the fewest route changes and limits the result set to the first occurrence.

// find all of the shortest paths that match the beginning and ending nodes
match p=allShortestPaths((a:Place {name: 'A'})-[:FOLLOWS*]->(d:Place {name: 'D'}))

// carry forward the path, the relationships in the path and a range that represents the second to last relationships in the path 
with p,relationships(p) as rel, range(1,length(p)-1) as index

// use reduce to process the route attribute on the relationship to accumulate the changes
with p, rel, index, reduce (num_chg = 0, i in index | num_chg + 
    case when (rel[i]).route = (rel[i-1]).route then 0 else 1 end ) as changes

// return the path and the number of route changes
return p, changes

// only return the path with the fewest route change
order by changes
limit 1



回答2:


@DevBennett's answer gets the shortest path with the minimum number of route changes.

To get the shortest path with the minimum number of different routes, which is what the question literally asked for (but which may not have been what the asker actually wanted), you can use this query:

MATCH p=ALLSHORTESTPATHS((a:Place {name: "A"})-[:FOLLOWS*]->(d:Place{name:"D"}))
UNWIND RELATIONSHIPS(p) AS rel 
WITH p, COUNT(DISTINCT rel.route) AS nRoutes 
RETURN p, nRoutes 
ORDER BY nRoutes 
LIMIT 1;



回答3:


Come on, you could not be happy with only 3 answers :)

MATCH (a:Place {name:"A"}), (d:Place {name:"D"})
MATCH p=allShortestPaths((a)-[*]->(d))
RETURN p, 
size(filter(x in range(0, size(rels(p))) 
       WHERE (rels(p)[x]).route <> (rels(p)[x-1]).route)) + length(p) as score
ORDER BY score ASC



回答4:


Something like this:

MATCH 
    (a:place {name: "A"}) WITH a
MATCH
    (d:place {name: "D"}) WITH a,d 
MATCH
    p = allShortestPaths  ( (a)-[:FOLLOWS*..100]->(d) )
WITH 
    nodes(p) as places, relationships(p) as paths
UNWIND
    paths as path
WITH
    places, paths, collect(distinct path.route) as segments
RETURN
    places, paths, segments, size(segments) as cost
ORDER BY
    cost ASC
LIMIT 1



回答5:


The answers using "AllShortestPaths" are wrong.

What if the graph looks like the image below?

Example of Graph Well, the result of the queries using AllShortestPaths function will be "A-E-D" and not "A-B-C-D" ...



来源:https://stackoverflow.com/questions/36583941/how-to-find-the-shortest-path-with-the-minimum-number-of-hops-in-neo4j

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!