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
相关产品推荐
相关产品推荐

