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

MongoDB按日期与类型嵌套分组聚合及卡路里求和实现咨询

MongoDB嵌套分组聚合需求与解决方案

问题背景

我在MongoDB中有一个名为entries的集合,数据结构如下:

[
   {
      "date": "Mon Jul 07 2022 17:15:19",
      "name": "Banana",
      "calories": 100,
      "mealID": "62d55d4de4c92d6de31e22ad",
      "type": "Lunch"
    },
    {
      "date": "Mon Jul 07 2022 17:15:19",
      "name": "Buger",
      "calories": 300,
      "mealID": "62d55d4de4c92d6de31e22ad",
      "type": "Lunch"
     },
     {
      "date": "Mon Jul 07 2022 17:15:19",
      "name": "Coffee",
      "calories": 120,
      "mealID": "62d55d4de4c92d6de31e22",
      "type": "Break fast"
     },
     {
      "date": "Mon Jul 07 2022 17:15:19",
       "name": "Omlet",
       "calories": 70,
       "mealID": "62d55d4de4c92d6de31e22ad",
       "type": "Dinner"
      }
]

期望结果

需要对该集合执行聚合操作,按date和type(Lunch/Break fast/Dinner)进行嵌套分组,同时按日期统计总卡路里,最终结果格式如下:

[
   { 
     _id: "Mon Jul 07 2022 17:15:19",
     entriesForTheDay: {
        "Dinner": {
          entries: [
            {name: "Omlet", calories: 70},
          ],
          count: 1,
        },
        "Break fast": {
          entries: [
            {name: "Coffee", calories: 120},
          ],
          count: 1,
        },
        "Lunch": {
          entries: [
            {name: "Banana", calories: 100},
            {name: "Buger", calories: 300},
          ],
          count: 2,
        }
     },
     totalCaloriesForThDay: 590
   }
]

尝试的代码

我尝试了以下聚合代码,但不清楚如何按$type字段进行分组:

[
 {$group: {_id: '$date',
                   entries: {
                        $push: {
                            entry: {
                                name: '$name',
                                calories: '$calories',
                                type: '$type'
                            },
                           }
                        },
                        count: {
                            "$sum": 1
                        }
                    }
                },
]

解决方案

要实现嵌套分组并生成目标格式,需要分三步构建聚合管道:

  1. 按date+type复合键分组,统计每个餐型的条目、数量和卡路里;
  2. 按date聚合,将各餐型数据整理为键值对数组;
  3. 将数组转为嵌套对象,同时计算当日总卡路里。

完整的聚合代码如下:

db.entries.aggregate([
  // 第一步:按日期+餐型分组,收集条目、统计数量和餐型卡路里
  {
    $group: {
      _id: {
        date: "$date",
        type: "$type"
      },
      entries: {
        $push: {
          name: "$name",
          calories: "$calories"
        }
      },
      count: { $sum: 1 },
      typeCalories: { $sum: "$calories" }
    }
  },
  // 第二步:按日期分组,整理餐型数据为键值对数组,累加当日总卡路里
  {
    $group: {
      _id: "$_id.date",
      entriesForTheDay: {
        $push: {
          k: "$_id.type",
          v: {
            entries: "$entries",
            count: "$count"
          }
        }
      },
      totalCaloriesForThDay: { $sum: "$typeCalories" }
    }
  },
  // 第三步:将键值对数组转为嵌套对象,匹配目标格式
  {
    $addFields: {
      entriesForTheDay: { $arrayToObject: "$entriesForTheDay" }
    }
  }
])

代码说明

  • 第一层$group:用复合_id确保每个日期下的不同餐型单独聚合,收集对应条目、统计餐型内的条目数量和卡路里总和;
  • 第二层$group:按日期聚合所有餐型数据,用$push生成包含餐型名称(k)和餐型详情(v)的数组,同时累加所有餐型的卡路里得到当日总摄入;
  • $addFields阶段:通过$arrayToObject将数组结构的餐型数据转为嵌套对象,完全匹配期望的entriesForTheDay格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 06:45:41