在 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 数据库)引发的,我用于测试。
我有一组像这样的 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 数据库)引发的,我用于测试。