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

MongoDB多阶段Group By未达预期输出,求正确聚合方案

MongoDB嵌套分组聚合解决方案

问题概述

需要对集合中的文档进行聚合分组,将相同顶层Id的文档合并为单文档,同时嵌套聚合用户及其关联的演唱会数据,形成指定的嵌套结构。

输入数据

[
  {
    "Id": "Id1",
    "Title": "Title1",
    "User": {
      "Id": "Userid1",
      "Title": "User Title1",
      "Concerts": {
        "Id": "Concert3",
        "Title": "Concert title3",
        "Users": {
          "Id": "Userid1",
          "Title": "User Title Concert3"
        }
      }
    }
  },
  {
    "Id": "Id1",
    "Title": "Title1",
    "User": {
      "Id": "Userid2",
      "Title": "User Title2",
      "Concerts": {
        "Id": "Concert1",
        "Title": "Concert title1",
        "Users": {
          "Id": "Userid2",
          "Title": "User Title2 Concert1"
        }
      }
    }
  },
  {
    "Id": "Id1",
    "Title": "Title1",
    "User": {
      "Id": "Userid2",
      "Title": "User Title1",
      "Concerts": {
        "Id": "Concert4",
        "Title": "Concert title1",
        "Users": {
          "Id": "Userid2",
          "Title": "User Title2 Concert4"
        }
      }
    }
  }
]

期望输出

{
    "Id": "Id1",
    "Title": "Title1",
    "User": [
        {
            "Id": "Userid2",
            "Title": "User Title1",
            "Concerts": [
                {
                    "Id": "Concert4",
                    "Title": "Concert title1",
                    "Users": {
                        "Id": "Userid2",
                        "Title": "User Title2 Concert4"
                    }
                },
                {
                    "Id": "Concert1",
                    "Title": "Concert title1",
                    "Users": {
                        "Id": "Userid2",
                        "Title": "User Title2 Concert1"
                    }
                }
            ]
        },
        {
            "Id": "Userid1",
            "Title": "User Title1",
            "Concerts": [
                {
                    "Id": "Concert1",
                    "Title": "Concert title1",
                    "Users": {
                        "Id": "Userid1",
                        "Title": "User Title Concert1"
                    }
                },
                {
                    "Id": "Concert2",
                    "Title": "Concert title1",
                    "Users": {
                        "Id": "Userid1",
                        "Title": "User Title Concert2"
                    }
                },
                {
                    "Id": "Concert3",
                    "Title": "Concert title1",
                    "Users": {
                        "Id": "Userid1",
                        "Title": "User Title Concert3"
                    }
                }
            ]
        }
    ]
}

尝试过的聚合管道

[
  {
    $group: {
      _id: {
        "id": "$_id",
        "userId": "$User.Id",
        "ConcertsId": "$User.Concerts.Id"
      },
      Title: {
        $first: "$Title"
      },
      User: {
        $addToSet: "$User"
      }
    }
  },
  {
    $group: {
      _id: {
        "id": "$_id",
        "userId": "$User.Id",
        "ConcertsId": "$User.Concerts.Id",
        "InnerUserId": "$User.Concerts.User.Id"
      },
      Title: {
        $first: "$Title"
      },
      User: {
        $addToSet: "$User"
      }
    }
  }
]

解答

1. Group By是实现该需求的正确选择

你的需求本质是多层级的分组聚合:先按顶层Id分组,再在每组内按用户Id分组,最后为每个用户聚合其关联的演唱会列表,$group(Group By)是完全适配这个需求的核心操作,只是之前的分组逻辑层级混乱,导致无法得到目标结构。

2. 正确的聚合管道实现

需要分三个阶段完成嵌套聚合:

[
  // 第一阶段:去重并提取基础数据
  {
    $group: {
      _id: {
        rootId: "$Id",
        userId: "$User.Id",
        concertId: "$User.Concerts.Id"
      },
      rootTitle: { $first: "$Title" },
      userTitle: { $first: "$User.Title" },
      concert: { $first: "$User.Concerts" }
    }
  },
  // 第二阶段:按用户聚合演唱会列表
  {
    $group: {
      _id: {
        rootId: "$_id.rootId",
        userId: "$_id.userId"
      },
      rootTitle: { $first: "$rootTitle" },
      userTitle: { $first: "$userTitle" },
      concerts: { $push: "$concert" }
    }
  },
  // 第三阶段:按顶层ID聚合用户列表
  {
    $group: {
      _id: "$_id.rootId",
      Title: { $first: "$rootTitle" },
      User: {
        $push: {
          Id: "$_id.userId",
          Title: "$userTitle",
          Concerts: "$concerts"
        }
      }
    }
  },
  // 可选:调整字段名匹配期望输出
  {
    $project: {
      _id: 0,
      Id: "$_id",
      Title: 1,
      User: 1
    }
  }
]

3. 管道逻辑说明

  • 第一阶段:通过三重分组(顶层ID、用户ID、演唱会ID)避免重复数据,同时提取各层级的标题和演唱会详情。
  • 第二阶段:基于第一阶段结果,按顶层ID和用户ID分组,用$push将同一用户的所有演唱会组装成列表。
  • 第三阶段:按顶层ID分组,将所有用户数据组装成列表,整理成目标字段结构。
  • 可选的$project阶段:将_id重命名为Id,移除冗余字段,完全匹配期望输出格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 08:23:01