如何使用cypher查询限制树中每一层子节点



我使用cypher和neo4j我有一个父母和孩子关系的大数据集

(:Person)-[:PARENT_OF*]-(:Person)

我需要在树的每个级别上获得只有5个子(节点)的家谱

我试过:

MATCH path = (jon:Person )-[:PARENT_OF*]-(:Person)
WITH collect(path) as paths
CALL apoc.convert.toTree(paths) yield value
RETURN value;

它返回给我整个树结构,我试过用limit限制节点,但它不能正常工作

我想你得先把路径过滤掉。我的方法是确保路径中的所有子节点都位于前一个父节点的前5个子节点中。我没有准备好测试它的数据集,但它可以沿着这个

的行。
MATCH path = (jon:Person )-[:PARENT_OF*]->(leaf:Person)
// limit the number of paths, by only considering the ones that are not parent of someone else.
WHERE NOT (leaf)-[:PARENT_OF]->(:Person)
// and all nodes in the path (except the first one, the root) be in the first five children of the parent
AND 
ALL(child in nodes(path)[1..] WHERE child IN [(sibling)<-[:PARENT_OF]-(parent)-[:PARENT_OF]->(child) | sibling][..5])
WITH collect(path) as paths
CALL apoc.convert.toTree(paths) yield value
RETURN value

另一种可能更快的方法是首先收集jon的后代的所有前五个子女

// find all sets of "firstFiveChildren"
MATCH (jon:Person { name:'jon'}),
(p:Person)-[:PARENT_OF]->(child)
WHERE EXISTS((jon)-[:PARENT_OF*]->(p))
WITH jon,p,COLLECT(child)[..5] AS firstFiveChildren
// create a unique list of the persons that could be part of the tree
WITH jon,apoc.coll.toSet(
apoc.coll.flatten(
[jon]+COLLECT(firstFiveChildren)
)
) AS personsInTree

MATCH path = (jon)-[:PARENT_OF*]->(leaf:Person)
WHERE NOT (leaf)-[:PARENT_OF]->(:Person)
AND ALL(node in nodes(path) WHERE node IN personsInTree)
WITH collect(path) as paths
CALL apoc.convert.toTree(paths) yield value
RETURN value;

更新数据的问题是树不是对称的,例如不是所有的路径都有相同的深度。例如,节点d0没有子节点。因此,如果你在第一层选择了五个子节点,你可能不会再深入了。

我添加了一种稍微不同的方法,它应该适用于对称树,并且允许您设置每个节点的最大子节点数。用3试试,你会发现你只能得到第一个关卡的节点。, 8你得到的更多。

// find all sets of "firstChildren"
WITH 8 AS numberChildren
MATCH (jon:Person { name:'00'}),
(p:Person)-[:PARENT_OF]->(child)
WHERE EXISTS((jon)-[:PARENT_OF*0..]->(p))
WITH jon,p,COLLECT(child)[..numberChildren] AS firstChildren
// create a unique list of the persons that could be part of the tree
WITH jon,apoc.coll.toSet(
apoc.coll.flatten(
[jon]+COLLECT(firstChildren)
)
) AS personsInTree

MATCH path = (jon)-[:PARENT_OF*]->(leaf:Person)
WHERE NOT (leaf)-[:PARENT_OF]->(:Person)
AND ALL(node in nodes(path) WHERE node IN personsInTree)
WITH collect(path) as paths
CALL apoc.convert.toTree(paths) yield value
RETURN value

最新更新