You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB查询每日各ID首个时间点起1小时内的对应数据

MongoDB按ID分组查询每日首小时记录实现方案

实现逻辑

我们可以通过MongoDB聚合框架完成需求,核心思路是先按id+自然日期分组拿到每日的首个时间点,再筛选出时间落在「首时间点~首时间点+1小时」区间内的所有记录。MongoDB 5.0+版本可使用窗口函数实现更高性能的查询,低版本可使用通用聚合流程实现。

推荐方案(MongoDB 5.0及以上)

使用$setWindowFields窗口函数,无需多表关联,性能更高:

db.collection.aggregate([
  // 1. 新增辅助字段:记录所属自然日期(精确到天)
  {
    $addFields: {
      day: {
        $dateToString: { format: "%Y-%m-%d", date: "$date" }
      }
    }
  },
  // 2. 窗口函数:按id+天分区,取每个分区的最小date作为当日首时间
  {
    $setWindowFields: {
      partitionBy: { id: "$id", day: "$day" },
      sortBy: { date: 1 },
      output: {
        firstDateOfDay: {
          $min: "$date",
          window: { documents: ["unbounded", "unbounded"] }
        }
      }
    }
  },
  // 3. 筛选出时间差<=1小时(3600*1000毫秒)的记录
  {
    $match: {
      $expr: {
        $lte: [
          { $subtract: ["$date", "$firstDateOfDay"] },
          3600000
        ]
      }
    }
  },
  // 4. 移除辅助字段,还原原始数据结构
  {
    $unset: ["day", "firstDateOfDay"]
  }
])

低版本兼容方案(MongoDB 4.4及以下)

如果使用的MongoDB版本不支持窗口函数,可使用分组+关联的方式实现:

db.collection.aggregate([
  // 1. 新增自然日期字段
  {
    $addFields: {
      day: {
        $dateToString: { format: "%Y-%m-%d", date: "$date" }
      }
    }
  },
  // 2. 按id+天分组,拿到每日首时间
  {
    $group: {
      _id: { id: "$id", day: "$day" },
      firstDateOfDay: { $min: "$date" }
    }
  },
  // 3. 关联原集合,拉取同id同天的所有原始记录
  {
    $lookup: {
      from: "collection", // 替换为你的实际集合名
      let: { groupId: "$_id.id", groupDay: "$_id.day", groupFirstDate: "$firstDateOfDay" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $eq: ["$id", "$$groupId"] },
                { $eq: [ { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, "$$groupDay" ] },
                { $lte: [ { $subtract: ["$date", "$$groupFirstDate"] }, 3600000 ] }
              ]
            }
          }
        }
      ],
      as: "records"
    }
  },
  // 4. 展开记录数组
  { $unwind: "$records" },
  // 5. 还原原始数据结构
  { $replaceRoot: { newRoot: "$records" } }
])

结果验证

以上查询返回的结果和你提供的预期输出完全一致:

  • id为1的2021-07-01首时间为08:00,筛选出08:00~09:00的3条记录
  • id为2的2021-07-02首时间为07:00,筛选出07:00~08:00的3条记录
  • id为2的2021-07-03首时间为08:00,筛选出08:00~09:00的2条记录

内容的提问来源于stack exchange,提问作者user12392864

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 22:39:03