如何在 Spring Data Neo4j 中获取节点及其所有 children
How to fetch nodes and all their children in Spring Data Neo4j
我有这个 Neo4j 节点 class:
@Node
@Data
@AllArgsConstructor
public class Person {
@Id
@GeneratedValue
private Long id;
private Long parentId;
@Relationship(type = "PARENT_OF", direction = Relationship.Direction.OUTGOING)
private List<Person> children;
public Person addChild(Person person) {
person.setParentId(this.id);
this.children.add(person);
return this;
}
}
我想构建一个查询以与 Spring Data @Query 注释一起使用,以获取系谱树列表,其中根的 parentId 为空。对于每个根,我还想获取他们的 children,对于每个 child 他们自己的 children,等等
到目前为止,我能想到的最好的是:
public interface PersonRepository extends Neo4jRepository<Person, Long> {
@Query("""
MATCH (person:Person)
WHERE person.parentId IS NULL
OPTIONAL MATCH (person)-[parentOf:PARENT_OF]->(children)
RETURN person, collect(parentOf), collect(children)
SKIP 0
LIMIT 10
""")
List<Person> findAllGenealogicalTrees();
}
但它似乎没有做我正在寻找的事情,因为它似乎只获取根的 children,而不是 [=] 的 children 34=]仁.
我的查询有问题吗?
编辑:
尝试了建议的查询:
MATCH path=(person)-[parentOf:PARENT_OF*]->(child)
WHERE person.parentId IS NULL
AND NOT (child)-[:PARENT_OF]->()
RETURN path
但结果列表似乎如下:
Person(id=0, parentId=null, children=[Person(id=1, parentId=0, children=[Person(id=3, parentId=1, children=[])])])
Person(id=1, parentId=0, children=[Person(id=3, parentId=1, children=[])])
Person(id=3, parentId=1, children=[])
我只期待第一条记录,因为 parentId 应该为空。为什么它会返回另外两个具有非空 parentId 的记录?
要获取所有路径,可以使用变长模式
MATCH path=(person)-[parentOf:PARENT_OF*]->(child)
WHERE person.parentId IS NULL
AND NOT (child)-[:PARENT_OF]->()
RETURN path
我认为我们可以同意,第一个查询本质上只进行一次跳跃,因为您使用 (person)-[parentOf:PARENT_OF]->(children)
明确表示您只想找到直接子项。
@Graphileon 给出的建议进入了正确的方向,但从其 return 部分仅提供了一组无序的节点和关系。
Spring Data Neo4j 只能假定所有人物都具有相同的重要性,因此 return 是所有人物的集合。
我的建议是继续使用基于路径的方法,但以 Spring Data Neo4j 和您同意的方式修改 return 语句 ;)
MATCH path=(person)-[:PARENT_OF*]->(child:Person)
WHERE person.parentId IS NULL
RETURN person, collect(nodes(path)), collect(relationships(path))
另一种方法也可能是您在存储库中使用所谓的派生查找器方法:
List<Person> findAllByParentIdIsNull();
或者如果你想要它 pageable(不要忘记一些排序,否则数据可能会 return 随机编辑):
Page<Person> findAllByParentIdIsNull(Pageable pageable);
这将创建内部查询生成器,它将使用多个级联查询对数据进行探索性搜索(非基于路径的查询)。
在做出决定时(通常)有几点需要牢记:
- 如果您有很多跃点和分支导致响应时间相对较慢,那么基于路径的方法确实会增加数据库中的内存使用量。我认为这对您上面的域不会有问题,但这始终是我会关注的问题。
- 在这两种情况下(基于路径或级联查询),您最终都会得到三个数据桶:根节点、所有关系和所有相关节点。映射需要一些时间,因为 Spring Data Neo4j 必须将每个 returned 关系与它想要映射的每个关系的正确相关节点匹配。这没有任何问题,但具有循环映射域的结果。
我有这个 Neo4j 节点 class:
@Node
@Data
@AllArgsConstructor
public class Person {
@Id
@GeneratedValue
private Long id;
private Long parentId;
@Relationship(type = "PARENT_OF", direction = Relationship.Direction.OUTGOING)
private List<Person> children;
public Person addChild(Person person) {
person.setParentId(this.id);
this.children.add(person);
return this;
}
}
我想构建一个查询以与 Spring Data @Query 注释一起使用,以获取系谱树列表,其中根的 parentId 为空。对于每个根,我还想获取他们的 children,对于每个 child 他们自己的 children,等等
到目前为止,我能想到的最好的是:
public interface PersonRepository extends Neo4jRepository<Person, Long> {
@Query("""
MATCH (person:Person)
WHERE person.parentId IS NULL
OPTIONAL MATCH (person)-[parentOf:PARENT_OF]->(children)
RETURN person, collect(parentOf), collect(children)
SKIP 0
LIMIT 10
""")
List<Person> findAllGenealogicalTrees();
}
但它似乎没有做我正在寻找的事情,因为它似乎只获取根的 children,而不是 [=] 的 children 34=]仁.
我的查询有问题吗?
编辑:
尝试了建议的查询:
MATCH path=(person)-[parentOf:PARENT_OF*]->(child)
WHERE person.parentId IS NULL
AND NOT (child)-[:PARENT_OF]->()
RETURN path
但结果列表似乎如下:
Person(id=0, parentId=null, children=[Person(id=1, parentId=0, children=[Person(id=3, parentId=1, children=[])])])
Person(id=1, parentId=0, children=[Person(id=3, parentId=1, children=[])])
Person(id=3, parentId=1, children=[])
我只期待第一条记录,因为 parentId 应该为空。为什么它会返回另外两个具有非空 parentId 的记录?
要获取所有路径,可以使用变长模式
MATCH path=(person)-[parentOf:PARENT_OF*]->(child)
WHERE person.parentId IS NULL
AND NOT (child)-[:PARENT_OF]->()
RETURN path
我认为我们可以同意,第一个查询本质上只进行一次跳跃,因为您使用 (person)-[parentOf:PARENT_OF]->(children)
明确表示您只想找到直接子项。
@Graphileon 给出的建议进入了正确的方向,但从其 return 部分仅提供了一组无序的节点和关系。 Spring Data Neo4j 只能假定所有人物都具有相同的重要性,因此 return 是所有人物的集合。
我的建议是继续使用基于路径的方法,但以 Spring Data Neo4j 和您同意的方式修改 return 语句 ;)
MATCH path=(person)-[:PARENT_OF*]->(child:Person)
WHERE person.parentId IS NULL
RETURN person, collect(nodes(path)), collect(relationships(path))
另一种方法也可能是您在存储库中使用所谓的派生查找器方法:
List<Person> findAllByParentIdIsNull();
或者如果你想要它 pageable(不要忘记一些排序,否则数据可能会 return 随机编辑):
Page<Person> findAllByParentIdIsNull(Pageable pageable);
这将创建内部查询生成器,它将使用多个级联查询对数据进行探索性搜索(非基于路径的查询)。
在做出决定时(通常)有几点需要牢记:
- 如果您有很多跃点和分支导致响应时间相对较慢,那么基于路径的方法确实会增加数据库中的内存使用量。我认为这对您上面的域不会有问题,但这始终是我会关注的问题。
- 在这两种情况下(基于路径或级联查询),您最终都会得到三个数据桶:根节点、所有关系和所有相关节点。映射需要一些时间,因为 Spring Data Neo4j 必须将每个 returned 关系与它想要映射的每个关系的正确相关节点匹配。这没有任何问题,但具有循环映射域的结果。