我有一个包含时间戳的文档的MongoDB集合。它们形状的重要部分是:
{
receivedOn: {
date: ISODate("2018-10-01T07:50:06.836Z")
}
}
它们在日期被编入索引。
这些文档与不断到达服务器的UDP有关并包含来自UDP的数据。 UDP的速率有所不同,但通常约为每秒20个
我正在尝试从此收藏中取样。我有一个时间戳列表,我想获取过去最接近这些时间戳的文档。
例如,如果我有以下文件
{_id: 1, "receivedOn.date": ISODate("2018-10-01T00:00:00.000Z")}
{_id: 2, "receivedOn.date": ISODate("2018-10-01T00:00:02.000Z")}
{_id: 3, "receivedOn.date": ISODate("2018-10-01T00:00:04.673Z")}
{_id: 4, "receivedOn.date": ISODate("2018-10-01T00:00:05.001Z")}
{_id: 5, "receivedOn.date": ISODate("2018-10-01T00:00:09.012Z")}
{_id: 6, "receivedOn.date": ISODate("2018-10-01T00:00:10.065Z")}
和时间戳
new Date("2018-10-01T00:00:05.000Z")
new Date("2018-10-01T00:00:10.000Z")
我希望结果是
[
{_id: 3, "receivedOn.date": ISODate("2018-10-01T00:00:04.673Z")},
{_id: 5, "receivedOn.date": ISODate("2018-10-01T00:00:09.012Z")}
]
我使用汇总来完成这项工作。以下代码给出了正确的结果,但是速度慢并且似乎具有复杂性O(n*m)
,其中n
是匹配的文档数,而m
是时间戳数
const timestamps = [
new Date("2018-10-01T00:00:00.000Z")
new Date("2018-10-01T00:00:05.000Z")
new Date("2018-10-01T00:00:10.000Z")
];
collection.aggregate([
{$match: {
$and: [
{"receivedOn.date": {$lte: new Date("2018-10-01T00:00:10.000Z")}},
{"receivedOn.date": {$gte: new Date("2018-10-01T00:00:00.000Z")}}
]},
{$project: ...},
{$sort: {"receivedOn.date": -1}},
{$bucket: {
groupBy: "$receivedOn.date",
boundaries: timestamps,
output: {
docs: {$push: "$$CURRENT"}
}
}},
// The buckets contain sorted arrays. The first element is the newest
{$project: {
doc: {
$arrayElemAt: ["$docs", 0]
}
}},
// Lift the document out of its bucket wrapper
{$replaceRoot: {newRoot: "$doc"}}
]);
有没有办法使它更快?就像以某种方式告诉$bucket
数据已排序一样?我假设这里花费最多的时间是$bucket
试图弄清楚将文档放入哪个存储区。或者还有另一种更好的方法可以做到这一点?
我还尝试了每个时间戳并行运行一个findOne
查询。这样也可以给出正确的结果,并且速度更快,但是具有数千个时间戳的情况并不少见。我不想每次都需要执行数千个查询。