Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all childs of a particular node in neo4j

I have this relationship in my neo4j:

Parent -> Childs
F -> D,E
D -> A,B,C

Use case: I am trying to get all child of a particular node using this query

MATCH (p:Person{name:"F"})<-[:REPORTS_TO*]-(c) 
RETURN {parent : p.name, child : {name :collect( c.name)}}

This returns me this :

{"parent":"F","child":{"name":["D","A","B","C","E"]}}

A, B, C are not direct child of F as they are child of D

Required response is

[
"F" : [ Childs i.e "E", "D" ]
"E" : []
"D" : [ "A", "B", "C" ]
 and so on ....
]

One way to achieve this is fire this below query recursively :

MATCH (p:Person{name:"F"})<-[:REPORTS_TO]-(c) 
RETURN {parent : p.name, child : {name :collect( c.name)}}

Which returns

{"parent":"F","child":{"name":["E","D"]}}

Then search for all childs of E and D and then childs of childs and so on..

My question is can I achieve this in a single query or in a more better way?

Edit1 : Adding dataset

CREATE (f:Person {name: "F"})
CREATE (e:Person {name: "E"})
CREATE (d:Person {name: "D"})
CREATE (c:Person {name: "C"})
CREATE (b:Person {name: "B"})
CREATE (a:Person {name: "A"})
CREATE (x:Person {name: "X"})
CREATE (a)-[:REPORTS_TO]->(x)
CREATE (d)-[:REPORTS_TO]->(a)
CREATE (d)-[:REPORTS_TO]->(b)
CREATE (d)-[:REPORTS_TO]->(c)
CREATE (f)-[:REPORTS_TO]->(d)
CREATE (f)-[:REPORTS_TO]->(e)
like image 204
Prakash P Avatar asked Feb 05 '23 10:02

Prakash P


2 Answers

You can use OPTIONAL MATCH to achieve your goal.

Your data set looks like this:

Data set

Try it:

MATCH (p:Person)
OPTIONAL MATCH (p)<-[:REPORTS_TO]-(c) 
RETURN {parent : p.name, child : {name :collect( c.name)}}

Query results:

+-----------------------------------------------------+
| {parent : p.name, child : {name :collect( c.name)}} |
+-----------------------------------------------------+
| {parent=D, child={name=[C, B, A]}}                  |
| {parent=A, child={name=[]}}                         |
| {parent=C, child={name=[]}}                         |
| {parent=F, child={name=[E, D]}}                     |
| {parent=E, child={name=[]}}                         |
| {parent=B, child={name=[]}}                         |
+-----------------------------------------------------+

In case you need only a specific parent and yours respective children you can do:

MATCH (p:Person)
WHERE p.name = "D"
OPTIONAL MATCH (p)<-[:REPORTS_TO]-(c) 
WITH COLLECT (c) + p AS all
UNWIND all as p
MATCH (p)
OPTIONAL MATCH (p)<-[:REPORTS_TO]-(c) 
RETURN {parent : p.name, child : {name :collect( c.name)}}

As result:

+-----------------------------------------------------+
| {parent : p.name, child : {name :collect( c.name)}} |
+-----------------------------------------------------+
| {parent=D, child={name=[C, B, A]}}                  |
| {parent=A, child={name=[]}}                         |
| {parent=C, child={name=[]}}                         |
| {parent=B, child={name=[]}}                         |
+-----------------------------------------------------+

EDIT:

From the comment by @Prakash Pandey:

how can we do something like childs, childs of childs and so on where p.name = "Tom"

Based on the data set added in the question, you can do:

MATCH (p:Person)<-[:REPORTS_TO*]-(c:Person)
WHERE p.name = "X"
WITH COLLECT (c) + p AS all UNWIND all as p
MATCH (p)<-[:REPORTS_TO]-(c)
RETURN {parent : p.name, child : {name :collect( c.name)}}

Result:

+-----------------------------------------------------+
| {parent : p.name, child : {name :collect( c.name)}} |
+-----------------------------------------------------+
| {parent=D, child={name=[F]}}                        |
| {parent=A, child={name=[D]}}                        |
| {parent=X, child={name=[A]}}                        |
+-----------------------------------------------------+
like image 142
Bruno Peres Avatar answered Feb 08 '23 13:02

Bruno Peres


I created the graph you describe.

The following query returns most of what you need:

MATCH (a:Parent)<-[r:isParent*0..]-(b:Parent)
return {parent:a.name,child : {name :collect( b.name)}}

Result:

{"parent":"D","child":{"name":["D","A","B","C"]}}

{"parent":"A","child":{"name":["A"]}}

{"parent":"C","child":{"name":["C"]}}

{"parent":"F","child":{"name":["F","D","E","A","B","C"]}}

{"parent":"E","child":{"name":["E"]}}

{"parent":"B","child":{"name":["B"]}}

like image 42
anarche Avatar answered Feb 08 '23 12:02

anarche