utkarsh31
utkarsh31

Reputation: 1559

Recursively find all parent nodes for a given node in neo4j

I want to write a cypher query where given a node X, it gives all the parent nodes for that given node until I find the root node which has the type attribute as ROOT.

As an example, I have attached below image where my RootNode is the main parent node and it has attribute {type: "ROOT"}.

enter image description here

Example1: Find all parent nodes for a node with label TYPE2:X3 From the graph we can see, TYPE2:X3 has one parent nodes TYPE2:X1. Now TYPE2:X1 has two parents TYPE1:T1 and RootNode. Recursively, finding parent of TYPE1:T1 which is RootNode. Hence, the answer will be TYPE1:T1 and TYPE2:X1

Example2: Find all parent nodes for a node with label TYPE2:X4 From the graph we can see, TYPE2:X4 has 4 parent nodes TYPE1:T1, TYPE2:X1, TYPE2:X2, TYPE1:T2 who all have parent as RootNode so the answer will be these 4 nodes.

Please note that my graph can have upto 10 level of parent nodes like this.

Upvotes: 0

Views: 458

Answers (2)

cybersam
cybersam

Reputation: 67044

[UPDATED]

This query will return all distinct ancestor nodes by following all outbound relationships starting at a given n node, excluding any node that has no outbound relationships.

... // (prior Cypher providing n)

MATCH p = (n)-[*..8]->(root)
WHERE NOT EXISTS((root)-->())
UNWIND NODES(p)[1..-1] AS ancestor
RETURN DISTINCT ancestor

This query also puts an upper bound on the variable length pattern to avoid taking forever or running out of memory.

The x[1..-1] syntax specifies a sublist of x consisting of its second element up to and including its next-to-last element. (The documentation is a bit misleading, as it concentrates on the range() function, whereas specifying a sublist does not depend on using the range() function at all. The 2 concepts should have been covered separately.)

Upvotes: 0

Vincent Rupp
Vincent Rupp

Reputation: 655

The simplest thing to do is just traverse the graph with variable path length:

match path = (s)-[*..9]->()-->(e)
where s:X4 and s:TYPE2 and e:ROOT
with [n in nodes(path) where n <> e | n] as parentnodes
return parentnodes

Variable path length can make the query explode, especially if you have supernodes. If you have a fairly balanced tree structure like in your diagram, this may be okay.

UPDATE: This will make it so you don't need to know the label on the root node:

match path = (s)-[*..9]->()-->(e)
where s:X4 and S:TYPE2 and not (e)->()
with [n in nodes(path) where n <> e | n] as parentnodes
return parentnodes

Upvotes: 0

Related Questions