想象以下示例数据:
[
{
"_id": 1,
"category": "FIRE",
"time": "2024-05-11T07:11:00Z"
},
{
"_id": 2,
"category": "FIRE",
"time": "2024-05-11T08:11:00Z"
},
{
"_id": 3,
"category": "FIRE",
"time": "2024-05-11T09:11:00Z"
},
{
"_id": 4,
"category": "POLICE",
"time": "2024-05-11T07:22:00Z"
},
{
"_id": 5,
"category": "POLICE",
"time": "2024-05-11T08:22:00Z"
},
{
"_id": 6,
"category": "POLICE",
"time": "2024-05-11T09:22:00Z"
},
{
"_id": 7,
"category": "AMBULANCE",
"time": "2024-05-11T07:33:00Z"
},
{
"_id": 8,
"category": "AMBULANCE",
"time": "2024-05-11T08:33:00Z"
},
{
"_id": 9,
"category": "AMBULANCE",
"time": "2024-05-11T09:33:00Z"
}
]
对于一组类别(例如
["FIRE", "AMBULANCE"]
)和时间戳(例如["2024-05-11T08:15:00Z", "2024-05-11T09:00:00Z"]
)中的每个组合,我想在每个类别的每个时间戳上或之前获取latest条目:
[
{
"category": "FIRE",
"time": "2024-05-11T08:15:00Z",
"last_entry_on_or_before": {
"_id": 2,
"category": "FIRE",
"time": "2024-05-11T08:11:00Z"
}
},
{
"category": "FIRE",
"time": "2024-05-11T09:00:00Z",
"last_entry_on_or_before": {
"_id": 2,
"category": "FIRE",
"time": "2024-05-11T08:11:00Z"
}
},
{
"category": "AMBULANCE",
"time": "2024-05-11T08:15:00Z",
"last_entry_on_or_before": {
"_id": 7,
"category": "AMBULANCE",
"time": "2024-05-11T07:33:00Z"
}
},
{
"category": "AMBULANCE",
"time": "2024-05-11T09:00:00Z",
"last_entry_on_or_before": {
"_id": 8,
"category": "AMBULANCE",
"time": "2024-05-11T08:33:00Z"
}
}
]
这可以在单个高效聚合管道中完成吗?我在
[category, time]
上有一个复合索引。
您可以使用
$documents
来生成数组与 $unwind
的组合。然后,只需执行 $lookup
即可找到匹配的记录,然后将 $sort
和 $limit
链接起来即可获取最新记录。
db.aggregate([
{
"$documents": [
{
"category": //your input category array here
[
"FIRE",
"AMBULANCE"
],
//your input time array here
"time": [
"2024-05-11T08:15:00Z",
"2024-05-11T09:00:00Z"
]
}
]
},
{
"$unwind": "$category"
},
{
"$unwind": "$time"
},
{
"$lookup": {
"from": "collection",
"localField": "category",
"foreignField": "category",
"let": {
ts: "$time"
},
"pipeline": [
{
"$match": {
$expr: {
$lte: [
"$time",
"$$ts"
]
}
}
},
{
"$sort": {
"time": -1
}
},
{
"$limit": 1
}
],
"as": "last_entry_on_or_before"
}
},
{
"$unwind": "$last_entry_on_or_before"
}
])
playground 中的语法略有不同,因为
$documents
不允许直接在 Playground 中使用,需要解决这个问题。对于您实际的 mongo shell/其他驱动程序,上述语法应该有效。