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

Spring MongoTemplate内嵌对象字段投影及去重优化问题

MongoDB聚合投影嵌套字段到顶层类的问题

问题背景

原始MongoDB文档结构:

{
  "sourced": { "reference": "a", "otherField": 1 },
  "derived": "Q"
}

最终目标:将文档精简为仅包含顶层reference字段的结构,并去除重复数据:

{
  "reference": "a"
}

现有代码使用两个嵌套类可实现需求,但希望仅用一个包含reference属性的类。尝试Aggregation.project("sourced.reference")时,映射到类的字段返回null;尝试将sourced.reference投影到reference也未成功。

现有可行代码:

@Data
private static class ReducedEntity {
    Sourced sourced;
}

@Data
private static class Sourced {
    private String reference;
}

var aggregation = Aggregation.newAggregation(
        match(new Criteria()),
        Aggregation.project("sourced")
);
AggregationResults<ReducedEntity> results = mongoTemplate.aggregate(aggregation, collectionName, ReducedEntity.class);
List<ReducedEntity> mappedResult = results.getMappedResults();
return mappedResult.stream().map(book -> book.sourced.reference).collect(Collectors.toList());

解决方案

核心问题原因

直接用Aggregation.project("sourced.reference")时,MongoDB返回的结果结构是{"sourced.reference": "a"},而非顶层的{"reference": "a"},无法和单个类的reference属性匹配,导致字段为null。必须显式指定投影别名,将嵌套字段映射到顶层字段,同时添加去重逻辑。

实现代码

  1. 定义单个目标类:
@Data
private static class ReducedEntity {
    private String reference;
}
  1. 正确的聚合管道:
var aggregation = Aggregation.newAggregation(
        match(new Criteria()), // 保留原有查询条件
        // 显式将嵌套的sourced.reference映射为顶层reference字段
        Aggregation.project().and("sourced.reference").as("reference"),
        // 按reference分组实现去重,保留每个值的一条记录
        Aggregation.group("reference").first("reference").as("reference"),
        // 最终投影确保结构纯净,匹配目标类
        Aggregation.project("reference")
);

AggregationResults<ReducedEntity> results = mongoTemplate.aggregate(aggregation, collectionName, ReducedEntity.class);
List<ReducedEntity> mappedResult = results.getMappedResults();
// 如需转换为字符串列表,直接映射即可
List<String> referenceList = mappedResult.stream().map(ReducedEntity::getReference).collect(Collectors.toList());

代码说明

  • Aggregation.project().and("sourced.reference").as("reference"):强制将嵌套字段重命名为顶层的reference,确保和类属性名一致。
  • Aggregation.group("reference").first("reference").as("reference"):通过分组去重,避免返回重复的reference值。
  • 最后一次投影是为了过滤分组阶段产生的冗余字段,保证输出结构完全匹配目标类。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 15:53:37