Neo4j cypher query for linked list

1.5k views Asked by At

I have the below graph. A league (l1) starts with LEVEL r1 and the NEXT levels are related using NEXT relationship as shown.

league-[:LEVEL]->r1-[:NEXT]->r2-[:NEXT]->r3-[:NEXT]->r4

What I am looking for is to find all the levels for a given league and in the order. So, for the above graph the expected output is r1, r2, r3, r4. I've the below query but it is returning all the paths.

start l1=node(9)  match l1-[:level]->(level) with level match p=level-[:next*]->(remainingLevels) return p;

Cyphers for creating this graph. This is already setup on console.neo4j.org (make sure to change the id's)

CREATE (l1 {name: 'l1'}) return l1;
CREATE (r1 {name: 'r1'}) return r1;
START l1=node(9), r1=node(10) CREATE l1-[r:level]->r1;
CREATE (r2 {name: 'r2'}) return r2;
START r1=node(10), r2=node(11) CREATE r1-[r:next]->r2;
CREATE (r3 {name: 'r3'}) return r3;
START r2=node(11), r3=node(12) CREATE r2-[r:next]->r3;
CREATE (r4 {name: 'r4'}) return r4;
START r3=node(12), r4=node(13) CREATE r3-[r:next]->r4;
3

There are 3 answers

0
Edward On BEST ANSWER

I cleaned up your data set and attempted an answer here:

MATCH league-[r:level|next*]->(level) 
WHERE league.name?="l1" 
RETURN level, length(r) AS Dist, r 
ORDER BY length(r)

The query starts at a league (l1) and traces out across all :level and :next routes and then returns the nodes found sorted by the distance of the route taken to to arrive at it from the starting node.

Note this finds all possible routes, so if there are muliple ways to get to to the level, it won't work very well. That said, it appears your graph is quite tree-like (no cycles) and this will work fine.

This a 2.0 query because it relies on the WHERE query to utilize the indicies to get the starting node in the graph (l1).

3
Aravind Yarram On

I managed to get this working with the below query.

start l1=node(9) 
match l1-[:level]->(level) 
with level 
match p = level-[:next*]->(remainingLevels) 
with level, max(length(p)) as maxlen 
match p = level-[:next*]->(remainingLevels) 
where length(p)=maxlen
return nodes(p);

Output

+-----------------------------------------------------------------------------------+
==> | nodes(p)                                                                          |
==> +-----------------------------------------------------------------------------------+
==> | [Node[10]{name:"r1"},Node[11]{name:"r2"},Node[12]{name:"r3"},Node[13]{name:"r4"}] |
==> +-----------------------------------------------------------------------------------+

Any simplification or optimizations are welcome.

2
Lisa Li On

How about this query,

Match p=league1-[:level]->(level)-[:next*]->endLevel

WHERE league1.name ?= 'l1' AND NOT (endLevel-[:next]->())

RETURN tail(nodes(p))