如何在Spring Data MongoDB中实现指定文档的聚合查询
用Spring Data MongoDB实现你要的聚合结果
嘿,刚好做过类似的需求,我来一步步教你怎么搞定!首先咱们先理清楚核心需求:从你的文档里提取recruiters数组中的fullName,去重后整理成Agg数组的格式对吧?
第一步:先搞懂MongoDB原生聚合逻辑
先看底层的MongoDB聚合语句,这样你能明白每一步在做什么:
db.yourCollectionName.aggregate([ // 1. 把recruiters数组拆成单个独立文档,方便处理每个元素 { $unwind: "$recruiters" }, // 2. 按fullName分组去重,避免重复的名字出现 { $group: { _id: "$recruiters.fullName" } }, // 3. 重新格式化字段:把默认的_id换成fullName,去掉冗余的_id { $project: { _id: 0, fullName: "$_id" } }, // 4. 把所有去重后的fullName对象统一放到Agg数组里 { $group: { _id: null, Agg: { $push: "$$ROOT" } } }, // 5. 去掉最后不需要的_id字段 { $project: { _id: 0 } } ])
执行这个管道后,就能得到你想要的{ "Agg": [ { "fullName":"UserName1" }, { "fullName":"UserName2" } ] }结构。
第二步:用Spring Data MongoDB代码落地
接下来把这个管道转换成Spring Data的代码,这里用MongoTemplate+Aggregation类来实现,代码可读性拉满:
先准备实体类(可选,也可以用Map直接接收)
// 项目文档的实体类 @Document(collection = "yourCollectionName") public class Project { private ObjectId id; private String project; private List<Recruiter> recruiters; // getter、setter、构造器自己补一下就行 } // Recruiter的实体类(可以是内部类也可以独立) public class Recruiter { private String userId; private String fullName; // getter、setter、构造器省略 } // 用来接收聚合结果的DTO public class AggregationResult { private List<Recruiter> Agg; // getter、setter、构造器省略 }
编写聚合逻辑
在你的Service或者Repository里注入MongoTemplate,然后写聚合方法:
@Autowired private MongoTemplate mongoTemplate; public AggregationResult getAggregatedFullNames() { // 一步步构建聚合管道 Aggregation aggregation = Aggregation.newAggregation( // 对应原生的$unwind阶段 Aggregation.unwind("recruiters"), // 对应原生的$group去重阶段 Aggregation.group("recruiters.fullName"), // 对应原生的$project字段格式化 Aggregation.project().and("_id").as("fullName").andExclude("_id"), // 把所有结果收集到Agg数组里 Aggregation.group().push("$$ROOT").as("Agg"), // 去掉最后多余的_id Aggregation.project().and("Agg").as("Agg").andExclude("_id") ); // 执行聚合并映射到结果DTO AggregationResults<AggregationResult> results = mongoTemplate.aggregate( aggregation, "yourCollectionName", // 替换成你的集合名称 AggregationResult.class ); return results.getUniqueMappedResult(); }
验证结果
调用这个方法后,返回的AggregationResult对象序列化后就是你要的JSON格式:
{ "Agg": [ { "fullName":"UserName1" }, { "fullName":"UserName2" } ] }
如果不想定义实体类,也可以直接用Map.class替换AggregationResult.class,直接拿Map结果处理,灵活度更高。
内容的提问来源于stack exchange,提问作者opax
相关产品推荐
相关产品推荐

