MongoDB如何将subDocument数组首项提升至顶层并替换同名属性
实现方案
你可以通过MongoDB的聚合管道实现需求,分两种使用场景:
1. 仅查询返回转换后的结果(不修改原数据)
db.collection.aggregate([ // 提取subDocument数组第一个子项作为临时字段 { $addFields: { firstSub: { $first: "$subDocument" } // 版本低于4.4不支持$first时替换为: // firstSub: { $arrayElemAt: ["$subDocument", 0] } } }, // 合并顶层文档和子文档,子文档属性自动覆盖同名顶层属性 { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$firstSub"] } } }, // 移除不需要的冗余字段 { $project: { subDocument: 0, firstSub: 0 } } ])
2. 直接修改原集合的文档(MongoDB 4.2及以上版本支持)
db.collection.updateMany( // 此处填写需要匹配的文档条件,比如仅修改_id为1的文档就写{_id: 1} {}, [ { $set: { firstSub: { $first: "$subDocument" } } }, { $replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT", "$firstSub"] } } }, { $unset: ["subDocument", "firstSub"] } ] )
原理解释
$mergeObjects合并多个对象时,参数列表中越靠后的对象优先级越高,因此子文档的属性会自动覆盖顶层的同名属性,无需手动逐个指定要覆盖的字段- 仅需保留原文档的
_id和子文档全部属性的话,可以把$mergeObjects的参数改成[{_id: "$$ROOT._id"}, "$firstSub"],后续不需要再移除冗余字段,写法更简洁
内容的提问来源于stack exchange,提问作者harryk
相关产品推荐
相关产品推荐

