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

Spring MongoDB计算对象数组总和并映射DTO的问题

问题描述

集合结构

{
    _id:1,
    meterId:1,
    Date: 2021-03-01,
    consumption:[ 
        { value:10},
        {value:7}
    ]
}

期望返回结果

{
    meterId:1,
    Date: 2021-03-01,
    consumption:[ 
        { value:10},
        {value:7}
    ],
    total:17
}

自定义DTO

public class ConsumptionDTO {

    @Field("Date") // 映射文档中的大写Date字段
    protected Date date;

    protected String meterId;

    protected List<ConsumptionPoint> consumption;

    protected double total; // 新增字段
    
    // 构造方法、getter和setter
}

尝试的代码(存在问题)

List<ConsumptionDTO> consumptions =new ArrayList<>();

AggregationOperation filter = Aggregation.match(Criteria.where("meterId").in(meterIds).and("date").gte(startDate).lte(endDate));

AggregationOperation sum = Aggregation.group().sum("consumption.value").as("total");

Aggregation aggregation = Aggregation.newAggregation(filter, sum);

consumptions = mongoTemplate.aggregate(aggregation,collectionName,ConsumptionDTO.class).getMappedResults();
解决方案

问题分析

  • 字段大小写不匹配:MongoDB字段名区分大小写,文档中日期字段为Date(大写D),但代码中使用了date(小写d),导致match条件无法匹配到任何文档,聚合结果为空。
  • 错误使用group操作:Aggregation.group()不带分组键会将所有匹配文档合并为一个分组,且分组阶段会丢弃原文档的meterId、Date、consumption等字段,无法映射到ConsumptionDTO的完整结构。

修正后的实现

我们需要保留原文档所有字段,同时为每个文档计算consumption数组的总和,使用addFields操作新增total字段而非group:

List<ConsumptionDTO> consumptions = new ArrayList<>();

// 1. 修正字段大小写,匹配文档中的Date字段
AggregationOperation filter = Aggregation.match(
    Criteria.where("meterId").in(meterIds)
            .and("Date").gte(startDate).lte(endDate)
);

// 2. 用addFields为每个文档新增total字段,计算consumption.value的总和
AggregationOperation addTotalField = Aggregation.addFields()
    .addFieldWithValue("total", Aggregation.sum("consumption.value"))
    .build();

// 3. 组装聚合操作
Aggregation aggregation = Aggregation.newAggregation(filter, addTotalField);

// 4. 执行聚合并映射到DTO
consumptions = mongoTemplate.aggregate(aggregation, collectionName, ConsumptionDTO.class).getMappedResults();

补充说明

  • 必须给ConsumptionDTO的date字段添加@Field("Date")注解,否则Spring Data MongoDB无法正确映射文档中的大写Date字段到DTO的小写date属性。
  • addFields操作会保留原文档的所有字段,同时新增指定的total字段,完全符合期望的返回结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 10:35:24