在 spring 数据 mongo 聚合中正确使用 DateOperators.Month.withTimezone

Use DateOperators.Month.withTimezone correctly in a spring data mongo aggregation

我有一组像这样的 mongodb 文档

    * 1 */
{
    "_id" : ObjectId("613b21fe2e57a07bbacc18da"),
    "date" : ISODate("2021-07-31T22:00:00.000Z"),
    "initiativeId" : "613b17332e57a07bbacc164d",
    "studentClass" : "3A",
    "instituteId" : "60c89b7c1442725ff813733c",
    "values" : [ 
        {
            "mode" : "piedi",
            "distanceKm" : 12.2,
            "studentNumber" : 4
        }, 
        {
            "mode" : "pedibus",
            "distanceKm" : 4.2,
            "studentNumber" : 2
        }
    ]
}

/* 2 */
{
    "_id" : ObjectId("613b21fe2e57a07bbacc18dc"),
    "date" : ISODate("2021-09-06T22:00:00.000Z"),
    "initiativeId" : "613b17332e57a07bbacc164d",
    "studentClass" : "5C",
    "instituteId" : "60c89b7c1442725ff813733c",
    "values" : [ 
        {
            "mode" : "moto",
            "distanceKm" : 10.0,
            "studentNumber" : 1
        }
    ]
}

我正在使用 MongoDB 4.4。

我想使用 Spring 数据 Mongo (v2.2.5)

重现以下有效的 mongodb 查询
db.initiativeRecord.aggregate([
{ $addFields: { month: { year: {$year : "$date"}, 
                         month: {$month : { date: "$date", timezone: "Europe/Rome"}} 
                       } } },
{ $unwind : "$values" },
{ $group : { _id: {d: "$month", mode: "$values.mode"}, distance: {$sum: "$values.distanceKm" } } }
])

这是Spring数据mongo代码

  List<AggregationOperation> operations = new ArrayList<>();
    operations.add(Aggregation.unwind("values"));
    
       
    ProjectionOperation subProject = Aggregation.project("values")
        .and(DateOperators.Month.monthOf("date").withTimezone(Timezone.valueOf("Europe/Rome"))).as("month")
        .and(DateOperators.Year.year("$date")).as("year");
    operations.add(subProject);

    GroupOperation group = Aggregation.group("distance","year", "month","values.mode").sum("values.distanceKm").as("distance");
    project = project.andExpression("_id.mode").as("mode")
        .andExpression("_id.month").as("month")
        .andExpression("_id.year").as("year");

    operations.add(group);
    operations.add(project);

问题是在 $month 函数中使用了 timezone 属性

当我尝试添加这个时

DateOperators.Month.monthOf("date").withTimezone(Timezone.valueOf("Europe/Rome"))

执行抛出异常

Command failed with error 16006 (Location16006): 'can't convert from BSON type object to Date' on server localhost:40393. The full response is {"ok": 0.0, "errmsg": "can't convert from BSON type object to Date", "code": 16006, "codeName": "Location16006"}

当我删除 withTimezone 部分时

DateOperators.Month.monthOf("date")

执行没有抛出异常

我不明白如何在我的代码中正确使用 withTimezone

经过大量测试,我可以自己回答这个问题。我决定把它作为每个人的未来文档。

代码正确,适用于 MongoDb 4.4。 Spring 数据 mongodb 2.2.5 正确支持 DateOperators.Month.month.withTimeZone

异常是由 de.flapdoodle.embed.mongo(在我的例子中是 2.2.0 版)(嵌入式 mongo 数据库)引发的,我用于测试。