如何编写MongoDB聚合查询并在SpringBoot中实现父子文档分组?
针对你的需求,以下是MongoDB原生查询和SpringBoot中的具体实现方案:
MongoDB 原生查询实现
使用聚合管道完成自关联分组,直接在MongoShell中执行即可得到目标结构:
db.your_collection_name.aggregate([ // 自关联查询子文档:将parentID等于当前文档id的文档存入children数组 { $lookup: { from: "your_collection_name", localField: "id", foreignField: "parentID", as: "children" } }, // 筛选父级文档:仅保留parentID以Top_开头的记录 { $match: { parentID: { $regex: "^Top_" } } }, // 整理输出结构:只保留name和children字段,去除冗余的_id { $project: { _id: 0, name: 1, // 可选:如果需要过滤子文档的字段,用$map自定义输出,否则直接写children:1 children: { $map: { input: "$children", as: "child", in: { id: "$$child.id", name: "$$child.name", age: "$$child.age" } } } } } ])
执行后会返回类似如下格式的结果:
[ { "name": "A", "children": [ {"id": 3, "name": "Aa", "age": 12}, {"id": 3, "name": "Ab", "age": 8} ] }, { "name": "B", "children": [ {"id": 2, "name": "Ba", "age": 5}, {"id": 5, "name": "Ba", "age": 5}, {"id": 6, "name": "Ba", "age": 7} ] } ]
SpringBoot 实现方案
1. 定义实体类
首先创建对应集合的实体(假设集合名为person):
import org.springframework.data.mongodb.core.mapping.Document; import java.util.List; @Document(collection = "person") public class Person { private Integer id; private String name; private Integer age; private String parentID; private List<Person> children; // 存储子文档列表 // 手动生成getter、setter,或使用Lombok的@Data注解 public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public String getParentID() { return parentID; } public void setParentID(String parentID) { this.parentID = parentID; } public List<Person> getChildren() { return children; } public void setChildren(List<Person> children) { this.children = children; } }
2. 方式一:使用 MongoTemplate
通过MongoTemplate构建聚合管道:
import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.aggregation.Aggregation; import org.springframework.data.mongodb.core.aggregation.AggregationResults; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.stereotype.Service; import java.util.List; @Service public class PersonService { private final MongoTemplate mongoTemplate; // 构造注入MongoTemplate public PersonService(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } public List<Person> getParentsWithChildren() { Aggregation aggregation = Aggregation.newAggregation( // 自关联查询子文档 Aggregation.lookup("person", "id", "parentID", "children"), // 筛选父级文档 Aggregation.match(Criteria.where("parentID").regex("^Top_")), // 投影需要的字段,排除_id Aggregation.project("name", "children").andExclude("_id") ); AggregationResults<Person> results = mongoTemplate.aggregate(aggregation, "person", Person.class); return results.getMappedResults(); } }
3. 方式二:使用 MongoRepository + @Aggregation 注解
直接在Repository接口中定义聚合查询:
import org.springframework.data.mongodb.repository.Aggregation; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.List; public interface PersonRepository extends MongoRepository<Person, Integer> { @Aggregation(pipeline = { "{$lookup: {from: 'person', localField: 'id', foreignField: 'parentID', as: 'children'}}", "{$match: {parentID: {$regex: '^Top_'}}}", "{$project: {_id: 0, name: 1, children: 1}}" }) List<Person> findParentsWithChildren(); }
在业务代码中直接注入PersonRepository并调用findParentsWithChildren()方法即可。
内容的提问来源于stack exchange,提问作者user1351757
相关产品推荐
相关产品推荐

