简体   繁体   中英

Neo4J - Cypher: shortest path between multiple nodes

Let's say we have 4 nodes:

{id:1, name:"one"} {id:2, name:"two"} {id:3, name:"three"} {id:4, name:"four"}

Suppose node 1 is linked to node 2, node 2 to 3, 3 to 4 so the result would be something like:

(1)-->(2)-->(3)-->(4)

How would I be able to get the shortest path between multiple given nodes in any given order? A few examples:

findShortestPath(2,4,3) should result in: (2)-->(3)-->(4)

findShortestPath(3,1) should result in: (1)-->(2)-->(3)

findShortestPath(4,1) should result in: (1)-->(2)-->(3)-->(4)

findShortestPath(3,2) should result in: (2)-->(3)

I have tried something like this, but I feel like I'm going the wrong way and it's not the most performant solution. Note that my query gets constructed programmatically since it can contain any number and kind of nodes.

If the input would be: (2),(3),(1)

That would result in a double for loop constructing something like this:

match p=allShortestPaths((p2)-[*]-(p3)),allShortestPaths((p2)-[*]-(p1)),allShortestPaths((p3)-[*]-(p1)) where p1.name="Keanu Reeves" and p2.name="Gene Hackman" and p3.name="Clint Eastwood" return p;

My problem is that I can't provide multiple nodes to the allShortestPaths() function. Only 2 nodes with 1 relation is allowed.

You can go through all the pairs of nodes, and check that the other nodes are in the possible paths between these pairs:

WITH ["Keanu Reeves", "Gene Hackman", "Clint Eastwood"] AS names
UNWIND names AS nn
  MATCH (n {name: nn})
  WITH collect(n) AS nds

UNWIND nds AS n1
  UNWIND nds AS n2
  WITH nds, n1, n2 WHERE id(n1) > id(n2)
    MATCH path = allShortestPaths((n1)-[*]-(n2))
    WITH nds, path WHERE ALL(n IN nds WHERE n IN nodes(path))
RETURN path ORDER BY length(path) ASC

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM