如何根据 MongoDB 集合中的匹配来过滤 JavaScript 数组?

问题描述 投票:0回答:1

我有一个 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"}]
,因为这是唯一符合条件的项目。

请注意,我不想迭代数组,为每一项进行一次数据库查询,而是看看是否可以仅通过一次数据库查询来完成此操作。

javascript mongodb
1个回答
0
投票

首先,使用

device_id:
而不是
timestamps
更正您的输入数据
2024-05-13
(额外的冒号)和
2024-05-12
数组,因为它与您的期望不符。

在单个查询中获得所需输出的聚合管道是:

  1. 设置一个与您的输入数组匹配的字段
    timestamps
    • 在 JS 中,您只需将其替换为管道中的
      { $set: { timestamps: timestamps } }
  2. 展开该数组
  3. 检查日期是否在所需的时间戳范围内。
  4. 仅投影/替换生成的时间戳项。
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" }
])

蒙戈游乐场

© www.soinside.com 2019 - 2024. All rights reserved.