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

如何编写MongoDB聚合管道按公共值分组嵌套对象数组并保留父字段

实现方案

你可以在现有聚合管道的基础上增加$group和$project阶段完成分组重组,完整管道如下:

[
  {
    '$match': {
      '_id': new ObjectId('60dd583e38a494001e7cbe01')
    }
  },
  {
    '$unwind': {
      'path': '$bookmarks', 
      'preserveNullAndEmptyArrays': false
    }
  },
  // 第一阶段分组:按用户+国家聚合同国书签
  {
    '$group': {
      '_id': {
        'userId': '$_id',
        'country': '$bookmarks.country'
      },
      // 保留所有用户原有字段
      'firstLogIn': { '$first': '$firstLogIn' },
      'lastLoggedIn': { '$first': '$lastLoggedIn' },
      'name': { '$first': '$name' },
      'provider': { '$first': '$provider' },
      'googleID': { '$first': '$googleID' },
      'email': { '$first': '$email' },
      'picture': { '$first': '$picture' },
      '__v': { '$first': '$__v' },
      // 同国书签汇总到数组
      'countryBookmarks': { '$push': '$bookmarks' }
    }
  },
  // 第二阶段分组:按用户聚合所有国家的书签对
  {
    '$group': {
      '_id': '$_id.userId',
      'firstLogIn': { '$first': '$firstLogIn' },
      'lastLoggedIn': { '$first': '$lastLoggedIn' },
      'name': { '$first': '$name' },
      'provider': { '$first': '$provider' },
      'googleID': { '$first': '$googleID' },
      'email': { '$first': '$email' },
      'picture': { '$first': '$picture' },
      '__v': { '$first': '$__v' },
      'bookmarkPairs': {
        '$push': {
          'k': '$_id.country',
          'v': '$countryBookmarks'
        }
      }
    }
  },
  // 重组输出结构
  {
    '$project': {
      'firstLogIn': 1,
      'lastLoggedIn': 1,
      'name': 1,
      'provider': 1,
      'googleID': 1,
      'email': 1,
      'picture': 1,
      '__v': 1,
      // 将国家-书签字典对转为对象
      'bookmarks': { '$arrayToObject': '$bookmarkPairs' }
    }
  }
]

格式说明

你之前期望的bookmarks为数组且直接包含"US":[]的写法不符合JSON规范,上述管道输出的合法结构如下,bookmarks为对象,键为国家代码,值为对应国家的书签数组:

{
  "_id": ObjectId("60dd583e38a494001e7cbe01"),
  "firstLogIn": ISODate("2021-07-01T05:51:30.253Z"),
  "lastLoggedIn": ISODate("2021-07-01T05:51:30.253Z"),
  "name": "First Last",
  "provider": "google",
  "googleID": "some google ID",
  "email": "email@gmail.com",
  "picture": "link to picture",
  "__v": 0,
  "bookmarks": {
    "US": [/* 所有美国地区的书签 */],
    "MX": [/* 所有墨西哥地区的书签 */],
    "HN": [/* 所有洪都拉斯地区的书签 */]
    // 其余国家以此类推
  }
}

如果确实需要bookmarks为数组格式,可将最后一步$project阶段的bookmarks字段替换为如下配置:

'bookmarks': {
  '$map': {
    'input': '$bookmarkPairs',
    'in': {
      '$arrayToObject': [['$$this.k', '$$this.v']]
    }
  }
}

输出结构为:

"bookmarks": [
  {"US": [/* 美国地区书签 */]},
  {"MX": [/* 墨西哥地区书签 */]}
  // 其余国家以此类推
]

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 15:12:02