kpenza
kpenza

Reputation: 114

Neo4J path enumeration

Currently am working to analyse the different paths between two nodes. For this purpose I require some way to uniquely identify a path from the paths returned by Neo4J.

Test case:

#MATCH (n:City) DETACH DELETE n;
CREATE (n:City { name: 'Rome' });
CREATE (n:City { name: 'London' });
CREATE (n:City { name: 'Berlin' });
CREATE (n:City { name: 'Madrid' });
MATCH (n:City),(m:City)
WHERE n.name = 'London' AND m.name = 'Madrid'
CREATE (n)-[r:Connected]->(m) RETURN r;
MATCH (n:City),(m:City)
WHERE n.name = 'Madrid' AND m.name = 'Berlin'
CREATE (n)-[r:Connected]->(m) RETURN r;
MATCH (n:City),(m:City)
WHERE n.name = 'Berlin' AND m.name = 'Rome'
CREATE (n)-[r:Connected]->(m) RETURN r;
MATCH (n:City),(m:City)
WHERE n.name = 'London' AND m.name = 'Berlin'
CREATE (n)-[r:Connected]->(m) RETURN r;
MATCH (n:City),(m:City) WHERE n.name = 'London' AND m.name = 'Rome'
CREATE (n)-[r:Express]->(m) RETURN r;

The below query works fine

MATCH (n:City),(m:City)
WHERE n.name = 'London' AND m.name = 'Rome'
with n,m
match p= (n)-[*1..]->(m)
return p;

+---------------------------------------------------------------------------------------------------------------------------------------------+
| p                                                                                                                                                      |
+---------------------------------------------------------------------------------------------------------------------------------------------+
| (:City {name: "London"})-[:Connected]->(:City {name: "Madrid"})<-[:Connected]-(:City {name: "Berlin"})-[:Connected]->(:City {name: "Rome"}) |
| (:City {name: "London"})-[:Connected]->(:City {name: "Berlin"})<-[:Connected]-(:City {name: "Rome"})                                        |
| (:City {name: "London"})-[:Express]->(:City {name: "Rome"})                                                                                 |
+---------------------------------------------------------------------------------------------------------------------------------------------+

To get the visited nodes I used the query:

MATCH (n:City),(m:City)
WHERE n.name = 'London' AND m.name = 'Rome'
with n,m
match p= (n)-[*1..]->(m)
unwind nodes(p) as n1 return n1;

+--------------------------+
| n1                       |
+--------------------------+
| (:City {name: "London"}) |
| (:City {name: "Madrid"}) |
| (:City {name: "Berlin"}) |
| (:City {name: "Rome"})   |
| (:City {name: "London"}) |
| (:City {name: "Berlin"}) |
| (:City {name: "Rome"})   |
| (:City {name: "London"}) |
| (:City {name: "Rome"})   |
+--------------------------+

However, I need an attribute to determine the path from which the nodes was obtained, such as

+--------------------------+---------+
| n1                       | pathid  |
+--------------------------+---------+
| (:City {name: "London"}) | 1       |
| (:City {name: "Madrid"}) | 1       |
| (:City {name: "Berlin"}) | 1       |
| (:City {name: "Rome"})   | 1       |
| (:City {name: "London"}) | 2       |
| (:City {name: "Berlin"}) | 2       |
| (:City {name: "Rome"})   | 2       |
| (:City {name: "London"}) | 3       |
| (:City {name: "Rome"})   | 3       |
+--------------------------+---------+

I have tried to use cypher foreach and reduce operators with no success. Can you please provide me some pointers on how I can enumerate paths?

Thanks Kenneth

Upvotes: 1

Views: 175

Answers (1)

Dave Bennett
Dave Bennett

Reputation: 11216

I think something like this might fit the bill for you.

MATCH (n:City),(m:City)
WHERE n.name = 'London' AND m.name = 'Rome'
WITH n,m
MATCH p= (n)-[*1..]->(m)
WITH COLLECT(p) as paths
UNWIND RANGE(0,size(paths)-1) AS idx
UNWIND NODES(paths[idx]) AS city
RETURN city, idx

You could also re-write you test data like this if you wanted to put it on a little bit of diet.

CREATE (n1:City { name: 'Rome' })
CREATE (n2:City { name: 'London' })
CREATE (n3:City { name: 'Berlin' })
CREATE (n4:City { name: 'Madrid' })
CREATE (n2)-[:Connected]->(n4)
CREATE (n4)-[:Connected]->(n3) 
CREATE (n3)-[:Connected]->(n1) 
CREATE (n2)-[:Connected]->(n3)
CREATE (n2)-[:Express]->(n1);

Upvotes: 2

Related Questions