如何通过MongoDB聚合管道按Key合并对象为数组?
MongoDB聚合管道合并同Key对象为数组解决方案
示例输入数据
{ "_id": "doc_001", "title": "测试文档", "items": [ {"key": "A", "value": 10}, {"key": "B", "value": 20}, {"key": "A", "value": 30}, {"key": "C", "value": 50}, {"key": "B", "value": 40} ] }
期望输出结果
{ "_id": "doc_001", "title": "测试文档", "mergedItems": { "A": [{"key": "A", "value": 10}, {"key": "A", "value": 30}], "B": [{"key": "B", "value": 20}, {"key": "B", "value": 40}], "C": [{"key": "C", "value": 50}] } }
聚合管道实现代码
db.your_collection.aggregate([ // 1. 展开items数组,将每个数组元素转为独立文档 { $unwind: "$items" }, // 2. 按「原文档ID + items.key」复合键分组,收集同key的对象到数组 { $group: { _id: { docId: "$_id", title: "$title", // 保留需要的顶层字段,按需添加 key: "$items.key" }, itemList: { $push: "$items" } } }, // 3. 按原文档信息重新分组,将每个key的数组整理为{k: key值, v: 数组}格式的元素 { $group: { _id: { _id: "$_id.docId", title: "$_id.title" }, keyArrays: { $push: { k: "$_id.key", v: "$itemList" } } } }, // 4. 将keyArrays数组转为键值对对象,同时整理输出结构 { $project: { _id: "$_id._id", title: "$_id.title", mergedItems: { $arrayToObject: "$keyArrays" } } } ])
关键步骤说明
- $unwind:必须先展开
items数组,否则无法对数组内的单个对象进行分组操作。 - 第一次$group:用复合
_id确保仅合并同一文档内的同key对象,$push将同组对象收集为数组。 - 第二次$group:把同一文档的所有分组结果聚合,生成符合
$arrayToObject要求的数组结构(每个元素包含k和v字段)。 - $arrayToObject:将数组格式的分组结果转换为目标键值对对象,完成合并。
如果你的文档有其他顶层字段需要保留,只需在两次$group的_id中添加对应字段即可。
内容的提问来源于stack exchange,提问作者Joe
相关产品推荐
相关产品推荐

