我有一个 mongodb 集合,其中的每个文档代表一个“窗口”,带有
device_id
(字符串)、start_time
,可能还有 end_time
(都是时间戳)。
现在,给定一个包含对象的 JavaScript 数组,每个对象都有一个 device_id 和时间戳,我想构建一个 MongoDb 查询,该查询输出相同的数组,但仅包含集合中至少存在一个与
device_id
匹配的文档的对象
并且 timestamp
位于其“窗口”内部(即大于 start_time
且小于 end_time
,如果 end_time 存在)。
因此,给出集合“windows”中的以下文档:
{
"start_time": "2024-05-12T12:00:00Z",
"end_time": "2024-05-12T14:00:00Z",
"device_id:": "1"
},
{
"start_time": "2024-05-12T07:00:00Z",
"end_time": "2024-05-12T09:00:00Z",
"device_id:": "2"
},
{
"start_time": "2024-05-12T01:00:00Z",
"end_time": "2024-05-12T03:00:00Z",
"device_id:": "3"
}
和一个像这样的数组:
const timestamps = [
{ device_id: 1, timestamp: "2024-05-12T13:00:00Z"},
{ device_id: 3, timestamp: "2024-05-12T13:00:00Z"},
{ device_id: 4, timestamp: "2024-05-12T13:00:00Z"}
];
会导致
[{ device_id: 1, timestamp: "2024-05-13T13:00:00Z"}]
,因为这是唯一符合条件的项目。
请注意,我不想迭代数组,为每一项进行一次数据库查询,而是看看是否可以仅通过一次数据库查询来完成此操作。
首先,使用
device_id:
而不是 timestamps
更正您的输入数据 2024-05-13
(额外的冒号)和 2024-05-12
数组,因为它与您的期望不符。
在单个查询中获得所需输出的聚合管道是:
timestamps
{ $set: { timestamps: timestamps } }
db.windows.aggregate([
{
$set: {
timestamps: [
{ device_id: 1, timestamp: "2024-05-12T13:00:00Z" },
{ device_id: 3, timestamp: "2024-05-12T13:00:00Z" },
{ device_id: 4, timestamp: "2024-05-12T13:00:00Z" }
]
}
},
{ $unwind: "$timestamps" },
{
$match: {
$expr: {
$and: [
{ $eq: ["$device_id", { $toString: "$timestamps.device_id" }] },
{ $lte: ["$start_time", "$timestamps.timestamp"] },
{ $gte: ["$end_time", "$timestamps.timestamp"] }
]
}
}
},
{ $replaceWith: "$timestamps" }
])