如何用MongoDB的$project将含对象的数组转换为普通对象
MongoDB聚合转换configs结构方案
原始数据结构
[ { "date": "2022-12-03T12:16:52.403Z", "configs": [ { "name": "Shubham", "values": [ { "text": "172cm", "type": "Height" }, { "text": "80kg", "type": "Weight" }, { "text": "male", "type": "Gender" } ] } ] } ]
目标转换结构
[ { "date": "2022-12-03T12:16:52.403Z", "configs": { "name": "Shubham", "Height": "172cm", "Weight": "80kg", "Gender": "male" } } ]
聚合管道实现方案
结合$project和其他聚合操作符就能完成转换,分阶段的完整写法如下:
db.collection.aggregate([ // 提取configs数组的第一个元素到临时字段 { $addFields: { tempConfig: { $first: "$configs" } } }, // 将values数组转成键值对对象 { $addFields: { valueObj: { $arrayToObject: { $map: { input: "$tempConfig.values", as: "val", in: { k: "$$val.type", v: "$$val.text" } } } } } }, // 生成最终结构,合并字段并清理临时数据 { $project: { date: 1, configs: { $mergeObjects: [ { name: "$tempConfig.name" }, "$valueObj" ] }, tempConfig: 0, valueObj: 0 } } ])
如果确认每个文档的configs数组只有一个元素,还可以简化成单阶段$project:
db.collection.aggregate([ { $project: { date: 1, configs: { $mergeObjects: [ { name: { $first: "$configs.name" } }, { $arrayToObject: { $map: { input: { $first: "$configs.values" }, as: "val", in: { k: "$$val.type", v: "$$val.text" } } } } ] } } } ])
关键操作符说明
$first:提取数组的第一个元素,适配原始数据中configs为单元素数组的场景;如果configs有多个元素,需要先使用$unwind展开数组再处理。$map+$arrayToObject:把values数组中的type作为键、text作为值,转换成标准键值对对象。$mergeObjects:将name字段和转换后的键值对象合并成最终的configs结构。$project:控制最终输出的字段,保留date和新生成的configs,移除临时字段。
内容的提问来源于stack exchange,提问作者Shubham Ambastha
相关产品推荐
相关产品推荐

