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

MongoDB三层嵌套文档如何按parentId和日期分组聚合各字段总和

实现方案

你需要用MongoDB的聚合管道结合$objectToArray、$arrayToObject处理动态字段,具体管道步骤如下:

db.collection.aggregate([
  // 步骤1:拆分时间为年、月、日,同时把stats.type下的所有子对象合并打平
  {
    $addFields: {
      year: { $year: "$time" },
      month: { $month: "$time" },
      day: { $dayOfMonth: "$time" },
      // 把stats.type的所有值(a、b、c对应的对象)转成数组后拼接,拿到所有n:xx的键值对
      allStats: {
        $reduce: {
          input: { $objectToArray: "$stats.type" },
          initialValue: [],
          in: { $concatArrays: ["$$value", { $objectToArray: "$$this.v" }] }
        }
      }
    }
  },
  // 步骤2:把打平的键值对拆成独立文档,方便后续分组求和
  { $unwind: "$allStats" },
  // 步骤3:按parentId、年月日、n字段名分组,求和
  {
    $group: {
      _id: {
        parentId: "$parentId",
        year: "$year",
        month: "$month",
        day: "$day",
        nKey: "$allStats.k"
      },
      total: { $sum: "$allStats.v" }
    }
  },
  // 步骤4:重新按parentId、年月日分组,把所有n字段和值拼成一个对象
  {
    $group: {
      _id: {
        parentId: "$_id.parentId",
        year: "$_id.year",
        month: "$_id.month",
        day: "$_id.day"
      },
      nFields: { $push: { k: "$_id.nKey", v: "$total" } }
    }
  },
  // 步骤5:把nFields转成顶层字段,补全输出格式
  {
    $replaceRoot: {
      newRoot: {
        $mergeObjects: [
          { parentId: "$_id.parentId", year: { $toString: "$_id.year" }, month: { $toString: "$_id.month" }, day: { $toString: "$_id.day" } },
          { $arrayToObject: "$nFields" }
        ]
      }
    }
  },
  // 可选:按时间、parentId排序
  { $sort: { year: 1, month: 1, day: 1, parentId: 1 } }
])

逻辑说明

先通过$objectToArray把嵌套的动态对象转成数组,再用$reduce拼接所有子对象的键值对,就能拿到每条数据里所有n:xx的字段和对应值;拆分数组后分组求和,再重新组装成你需要的扁平化输出结构,完全适配你给出的样例输入输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 08:48:02