我有一个树结构的图形(不,更多的是DAG,因为我可以拥有多个父级)并且需要能够编写从平面列表中返回所有结果的查询,从特定节点开始(s )和向下。
我已经将我的一个用例简化为这个简单的例子。在这里的ascii表示中,n是我的节点,我附加了他们的id。 p是我的auth系统中的权限,但与问题相关的所有内容都标记了我需要向下递归以收集应由查询返回的节点的位置。
图表:
n1
^ ^
/ \
n2 n3<--p
^ ^
/ \
n4 n5
^
/
n6
如果它有用,这是我跑来拼凑这个简单例子的密码:
CREATE path=(n1:n{id:1})<-[:HAS_PARENT]-(n2:n{id:2}),
(n1)<-[:HAS_PARENT]-(n3:n{id:3})<-[:HAS_PARENT]-(n4:n{id:4}),
(n3)<-[:HAS_PARENT]-(n5:n{id:5}),
(n4)<-[:HAS_PARENT]-(n6:n{id:6})
MATCH (n{id:3})
CREATE (:p)-[:IN]->(n)
以下是我目前最好的查询:
MATCH (n:n)<--(:p)
WITH collect (n) as parents, (n) as n
OPTIONAL MATCH (c)-[:HAS_PARENT*]->(n)
WITH collect(c) as children, (parents) as parents
UNWIND (parents+children) as tree
RETURN tree
这将返回正确的结果集,并且与之前我没有使用任何收集/展开的一些尝试不同,结果会根据需要返回单列数据。
这是进行此类查询的最佳方式吗?令人惊讶的是,它比我想象的简单场景更复杂。我尝试了一些查询,其中我将根(我的查询中的“父母”)与使用UNION子句的“子”组合在一起,但是我没有找到一种方法来执行此操作而不重复查询与p的关系。在我的真实世界查询中,这是一个更昂贵的操作,我已经减少了这个例子,所以我不能运行它多次。
答案 0 :(得分:1)
这可能符合您的需求:
MATCH (c)-[:HAS_PARENT*0..]->(root:n)<--(:p)
RETURN root, COLLECT(c) AS tree
每个结果行将包含一个不同的root
节点和一个集合,如果它的树节点(包括根节点)。