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

Spring Data Mongo聚合中DateOperators.Month.withTimezone正确用法咨询

问题解决

报错原因

你遇到的报错是因为Spring Data Mongo v2.2.5版本的DateOperators系列API对MongoDB 4.0+的对象式日期函数参数支持不完善:带时区的$month会被生成为数组参数格式,而非MongoDB要求的{date: "", timezone: ""}对象格式,导致MongoDB无法识别参数类型,抛出类型转换错误。同时你编写的聚合步骤顺序、分组逻辑和目标原生查询也不匹配。

解决方案

推荐直接用自定义聚合操作的方式完全复现原生查询逻辑,不受Spring Data Mongo版本API兼容性限制,代码如下:

List<AggregationOperation> operations = new ArrayList<>();

// 对应原生查询的$addFields阶段,构造包含年、带时区月份的复合month字段
operations.add(context -> new Document("$addFields",
    new Document("month",
        new Document("year", new Document("$year", "$date"))
            .append("month", new Document("$month",
                new Document("date", "$date")
                    .append("timezone", "Europe/Rome")
            ))
    )
));

// 展开values数组
operations.add(Aggregation.unwind("values"));

// 按month复合字段+出行模式分组,求和总里程
operations.add(Aggregation.group(Fields.fields()
            .and("d", "month")
            .and("mode", "values.mode"))
    .sum("values.distanceKm")
    .as("distance")
);

// 可选:将分组结果的嵌套字段展开为顶级字段,去掉_id
operations.add(Aggregation.project("distance")
    .and("_id.mode").as("mode")
    .and("_id.d.year").as("year")
    .and("_id.d.month").as("month")
    .andExclude("_id")
);

// 执行聚合查询,替换代码中的【结果接收类】为你自己定义的映射类
Aggregation aggregation = Aggregation.newAggregation(operations);
AggregationResults<结果接收类> results = mongoTemplate.aggregate(
    aggregation, "initiativeRecord", 结果接收类.class
);

其他可选方案

如果你希望使用官方DateOperatorsAPI实现,可以将Spring Data Mongo版本升级到2.3.0及以上,该版本修复了带时区日期函数的参数生成格式问题,升级后原有withTimezone写法即可正常运行。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 18:57:00