如何在neo4j中获取特定节点的所有子节点

时间:2017-05-17 12:52:55

标签: neo4j cypher graph-databases

在我的neo4j中有这种关系

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

用例:我正在尝试使用此查询获取特定节点的所有子节点

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

这让我回答:

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

A, B, C不是F的直接子女,因为他们是D

的孩子

所需回复

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

实现此目的的一种方法是以递归方式触发以下查询:

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

返回

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

然后搜索E and D的所有孩子,然后搜索孩子的孩子等等。

我的问题是,我可以通过单个查询或更好的方式实现这一目标吗?

编辑1 :添加数据集

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)

2 个答案:

答案 0 :(得分:4)

您可以使用OPTIONAL MATCH来实现目标。

您的数据集如下所示:

Data set

试一试:

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

查询结果:

+-----------------------------------------------------+
| {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=[]}}                         |
+-----------------------------------------------------+

如果您只需要特定的父母和您的孩子,您可以这样做:

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)}}

结果:

+-----------------------------------------------------+
| {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=[]}}                         |
+-----------------------------------------------------+

修改

来自@Prakash Pandey的评论:

  

我们怎样才能做孩子,孩子的孩子等等   p.name =&#34;汤姆&#34;

根据问题中添加的数据集,您可以执行以下操作:

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)}}

结果:

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

答案 1 :(得分:2)

我创建了你描述的图表。

以下查询返回您需要的大部分内容:

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

结果:

  

{&#34;父&#34;:&#34; d&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; d&#34; &#34; A&#34;&#34; B&#34;&#34; C&#34;]}}

     

{&#34;父&#34;:&#34; A&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; A&#34; ]}}

     

{&#34;父&#34;:&#34; C&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; C&#34; ]}}

     

{&#34;父&#34;:&#34; F&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; F&#34; &#34; d&#34;&#34; E&#34;&#34; A&#34;&#34; B&#34;&#34; C&#34;]}}

     

{&#34;父&#34;:&#34; E&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; E&#34; ]}}

     

{&#34;父&#34;:&#34; B&#34;&#34;子&#34; {&#34;名称&#34;:[&#34; B&#34; ]}}