You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Data MongoTemplate多字段去重聚合查询遇空结果求助

Spring Data MongoTemplate聚合去重返回空结果修复

问题背景

作为MongoDB聚合查询新手,需在userDetails集合中对userId和user字段执行去重操作。在Robo 3T中执行以下聚合语句可得到正确结果,但对应的Spring Data MongoTemplate代码返回空结果:

原MongoDB聚合语句

db.userDetails.aggregate([
    {"$match" : {zip:"52034", city:"Delhi"}}, 
    // 按userId和user分组实现去重
    {"$group" : {_id : {userId:"$userId", user:"$user"}}}, 
    // 整理输出结构
    {"$project" : {_id:0, userId:"$_id.userId", user:"$_id.user"}}
])

出错的Java代码

MatchOperation matchOperation = Aggregation.match(
          new Criteria("zip").is(zipCode).and("city").is(cityName));
GroupOperation groupOperation = new GroupOperation(Fields.fields("userId", "user"));
ProjectionOperation projectionOperation = Aggregation.project().andExclude("_id").and("userId").nested(
        Fields.fields("_id.userId"))
        .and("user").nested(Fields.fields("_id.user"));
Aggregation  aggregation = Aggregation.newAggregation(matchOperation, groupOperation, projectionOperation);
AggregationResults<UserDTO> result = mongoTemplate.aggregate(aggregation, UserDetails.class, UserDTO.class);

版本信息:Spring Data MongoDB 3.0.7,Driver 4.0.4

问题原因

出错核心在于ProjectionOperation的写法错误:使用nested()方法会创建嵌套文档结构,而非从_id中提取字段值映射到顶级字段,导致最终返回的文档结构与UserDTO不匹配,因此无法正确映射得到结果。

修正后的代码

MatchOperation matchOperation = Aggregation.match(
        new Criteria("zip").is(zipCode).and("city").is(cityName));

// GroupOperation写法正确,无需修改
GroupOperation groupOperation = new GroupOperation(Fields.fields("userId", "user"));

// 修正ProjectionOperation:直接提取_id中的字段映射为顶级字段
ProjectionOperation projectionOperation = Aggregation.project()
        .andExclude("_id")
        .and("_id.userId").as("userId")
        .and("_id.user").as("user");

Aggregation aggregation = Aggregation.newAggregation(matchOperation, groupOperation, projectionOperation);
AggregationResults<UserDTO> result = mongoTemplate.aggregate(aggregation, UserDetails.class, UserDTO.class);

说明

修正后的ProjectionOperation会生成与原MongoDB聚合语句一致的$project阶段:

{"$project" : {_id:0, userId:"$_id.userId", user:"$_id.user"}}

这样返回的文档结构能正确匹配UserDTO的字段,即可得到预期的去重结果。

内容的提问来源于stack exchange,提问作者user2068260

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:23:17