我有以下数据(汽车):
[
{
"make" : “Ferrari”,
"model" : “F40",
"services" : [
{
"type" : "FULL",
“date_time" : ISODate("2019-10-31T09:00:00.000Z"),
},
{
"type" : "FULL",
"scheduled_date_time" : ISODate("2019-11-04T09:00:00.000Z"),
}
],
},
{
"make" : "BMW",
"model" : “M3",
"services" : [
{
"type" : "FULL",
"scheduled_date_time" : ISODate("2019-10-31T09:00:00.000Z"),
},
{
"type" : "FULL",
“scheduled_date_time" : ISODate("2019-11-04T09:00:00.000Z"),
}
],
}
]
使用Spring数据MongoDb,我想查询检索所有 Cars ,其中最后一个项目的 scheduled_date_time 服务数组在某个日期范围之间。
我先前在使用services数组中的第一项时使用的查询是:
mongoTemplate.find(Query.query(
where("services.0.scheduled_date_time").gte(fromDate)
.andOperator(
where("services.0.scheduled_date_time").lt(toDate))),
Car.class);
请注意0索引,因为它是第一个索引,而不是最后一个索引(对于我当前的要求)。
我认为使用聚合以及投影和.arrayElementAt(-1)
可以解决问题,但我还没有完全起作用。我目前的工作是:
Aggregation agg = newAggregation(
project().and("services").arrayElementAt(-1).as("currentService"),
match(where("currentService.scheduled_date_time").gte(fromDate)
.andOperator(where("currentService.scheduled_date_time").lt(toDate)))
);
AggregationResults<Car> results = mongoTemplate.aggregate(agg, Car.class, Car.class);
return results.getMappedResults();
感谢任何帮助建议。
谢谢
答案 0 :(得分:2)
此mongo聚合检索服务数组中最后一项的schedule_date_time在特定日期范围之间的所有Car。
$stateData = (array)json_decode(fread($file, filesize(public_path('india_state_city1.json'))));
我试图用spring-data-mongodb编写它,但是没有运气。
它们尚不支持 [{
$addFields: {
last: {
$arrayElemAt: [
'$services',
-1
]
}
}
}, {
$match: {
'last.scheduled_date_time': {
$gte: ISODate('2019-10-26T04:06:27.307Z'),
$lt: ISODate('2019-12-15T04:06:27.319Z')
}
}
}]
,请参阅here。
从2.2.0版开始,spring-data-mongodb包含Aggregation Repository Methods
上面的查询应该是
$addFields
此方法记录此查询
interface CarRepository extends MongoRepository<Car, String> {
@Aggregation(pipeline = {
"{ $addFields : { last:{ $arrayElemAt: [$services,-1] }} }",
"{ $match: { 'last.scheduled_date_time' : { $gte : '$?0', $lt: '$?1' } } }"
})
List<Car> getCarsWithLastServiceDateBetween(LocalDateTime start, LocalDateTime end);
}
日期参数解析不正确。我没有花很多时间使它工作。
如果您想要汽车ID,则可以使用。
[{ "$addFields" : { "last" : { "$arrayElemAt" : ["$services", -1]}}}, { "$match" : { "last.scheduled_date_time" : { "$gte" : "$2019-11-03T03:00:00Z", "$lt" : "$2019-11-05T03:00:00Z"}}}]
查询日志
public List<String> getCarsIdWithServicesDateBetween(LocalDateTime start, LocalDateTime end) {
return template.aggregate(newAggregation(
unwind("services"),
group("id").last("services.date").as("date"),
match(where("date").gte(start).lt(end))
), Car.class, Car.class)
.getMappedResults().stream()
.map(Car::getId)
.collect(Collectors.toList());
}