问题
I have a graph in neo4j where a node represents a city and a relationship represents roads connecting the cities. The relationships are weighted and have a property called 'distance'. I want to find the shortest (least weighted path) between two cities A and B. This is easily done using Dijkstra's algorithm. The tricky part is that I have a set of cities which are to be covered in the path from A to B. In other words, the path from A to B should cover all the waypoints, the order doesn't matter. Something like providing a source, destination and list of waypoints and optimize:true in Google API. I have tried this using Cypher with the below query-
match(s:City{ID:"A"})
match(f:City{ID:"B"})
match (n:City) where n.name in ['City1','City2','City3','City4']
with collect(n) as wps
match path=allshortestPaths((s)-[:ROADWAY*..9]->(f))
where ALL ( n in wps WHERE n in nodes(path) ) with path,
reduce(d=0, rel IN relationships(path)| d+rel.displacement) as
totaldistance,Extract (n in nodes(path)| n.name) as cities
return cities, totaldistance, tofloat(totaldistance) as TD order by
totaldistance
But this didn't work. Maybe because the path wasn't passing through all the waypoints. I am also trying to use A* or Dijkstra (using Neo4j Traversal) but not sure how to visit all the waypoints.
Thanks in advance!!
回答1:
Try using ANY
rather ALL
.
From the neo4j documentation
All
- Tests whether a predicate holds for all elements of this list.
whereas
Any
- Tests whether a predicate holds for at least one element in the list.
match(s:City{ID:"A"})
match(f:City{ID:"B"})
match (n:City) where n.name in ['City1','City2','City3','City4']
with collect(n) as wps
match path=allshortestPaths((s)-[:ROADWAY*..9]->(f))
where ANY ( n in wps WHERE n in nodes(path) ) with path,
reduce(d=0, rel IN relationships(path)| d+rel.displacement) as
totaldistance,Extract (n in nodes(path)| n.name) as cities
return cities, totaldistance, tofloat(totaldistance) as TD order by
totaldistance
Edit - We can change this to ensure that all cities are included by combining multiple ANY in the where clause:
match(s:City{ID:"A"})
match(f:City{ID:"B"})
with collect(n) as wps
match path=allshortestPaths((s)-[:ROADWAY*..9]->(f))
where ANY ( n in nodes(wps) WHERE n.name = 'City1' ) AND
ANY ( n in nodes(wps) WHERE n.name = 'City2)
with path,
reduce(d=0, rel IN relationships(path)| d+rel.displacement) as
totaldistance,Extract (n in nodes(path)| n.name) as cities
return cities, totaldistance, tofloat(totaldistance) as TD order by
totaldistance
来源:https://stackoverflow.com/questions/45808063/shortest-path-between-2-nodes-through-waypoints-in-neo4j