Neo4J - Cypher: shortest path between multiple nod

2019-08-24 04:08发布

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.

标签: neo4j cypher
1条回答
Summer. ? 凉城
2楼-- · 2019-08-24 04:23

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
查看更多
登录 后发表回答