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

MongoDB使用dateTrunc分组后按字段汇总对象数组错误计数

MongoDB时间序列集合按动态API汇总错误计数

我在MongoDB中使用时间序列集合,以1分钟粒度存储各类API的错误计数。API名称未知且可能变更,因此查询最好不要依赖静态API名称。

示例数据集

[
  {
    _time: ISODate("2022-03-22T00:00:00.000Z"),
    errors: [
      { api: "shipping", count: 10 },
      { api: "inventory", count: 100 }
    ]
  },
  {
    _time: ISODate("2022-03-22T00:01:00.000Z"),
    errors: [
      { api: "shipping", count: 20 },
      { api: "inventory", count: 200 }
    ]
  },
  {
    _time: ISODate("2022-03-22T00:02:00.000Z"),
    errors: [ { api: "inventory", count: 300 } ]
  },
  {
    _time: ISODate("2022-03-22T00:03:00.000Z"),
    errors: [
      { api: "inventory", count: 400 },
      { api: "account", count: 1 }
    ]
  }
]

已实现的分组代码

目前我已经能通过以下代码将文档按2分钟粒度的时间桶分组:

db.collection.aggregate([
  {
    $group: {
      _id: {
        $dateTrunc: {
          date: "$_time",
          unit: "minute",
          binSize: 2
        }
      }
    }
  }
])

需求

  • 使用$dateTrunc将文档分组到2分钟粒度的时间桶中
  • 汇总每个时间桶内各API的错误计数

期望结果

格式一(嵌套数组形式)

[
  {
    _time: ISODate("2022-03-22T00:00:00.000Z"),
    errors: [
      { api: "shipping", count: 30 },
      { api: "inventory", count: 300 }
    ]
  },
  {
    _time: ISODate("2022-03-22T00:02:00.000Z"),
    errors: [
      { api: "inventory", count: 700 },
      { api: "account", count: 1 }
    ]
  }
]

格式二(动态字段形式)

[
  {
    _time: ISODate("2022-03-22T00:00:00.000Z"),
    shipping: 30,
    inventory: 300
  },
  {
    _time: ISODate("2022-03-22T00:02:00.000Z"),
    inventory: 700,
    account: 1
  }
]

解决方案

实现格式一(嵌套数组)

通过展开错误数组、分组聚合、再重组结构来实现:

db.collection.aggregate([
  // 展开每个文档中的errors数组,每个API错误项成为独立文档
  { $unwind: "$errors" },
  // 按时间桶和API名称分组,汇总计数
  {
    $group: {
      _id: {
        timeBucket: {
          $dateTrunc: {
            date: "$_time",
            unit: "minute",
            binSize: 2
          }
        },
        api: "$errors.api"
      },
      totalCount: { $sum: "$errors.count" }
    }
  },
  // 按时间桶重新分组,将同一桶的API错误汇总到数组中
  {
    $group: {
      _id: "$_id.timeBucket",
      errors: {
        $push: {
          api: "$_id.api",
          count: "$totalCount"
        }
      }
    }
  },
  // 重命名_id为_time,整理输出结构
  {
    $project: {
      _id: 0,
      _time: "$_id",
      errors: 1
    }
  }
])

实现格式二(动态字段)

在上述基础上,使用$arrayToObject将数组转换为动态字段:

db.collection.aggregate([
  { $unwind: "$errors" },
  {
    $group: {
      _id: {
        timeBucket: {
          $dateTrunc: {
            date: "$_time",
            unit: "minute",
            binSize: 2
          }
        },
        api: "$errors.api"
      },
      totalCount: { $sum: "$errors.count" }
    }
  },
  {
    $group: {
      _id: "$_id.timeBucket",
      apiCounts: {
        $push: {
          k: "$_id.api",
          v: "$totalCount"
        }
      }
    }
  },
  // 将apiCounts数组转换为键值对字段
  { $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          { _time: "$_id" },
          { $arrayToObject: "$apiCounts" }
        ]
      }
    }
  }
])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 11:15:37