MongoDB如何提取内嵌文档指定字段且不影响父文档原有字段
问题:如何提取内嵌文档的指定字段,同时不影响父文档中的原有字段?
约束说明
- 不清楚父文档的全部字段,无法显式指定包含所有父字段
- 不清楚内嵌文档的全部字段,无法显式指定排除不需要的内嵌字段
解决方案
核心逻辑是使用$addFields(MongoDB 3.4及以上版本支持,也可以使用等价别名$set)聚合阶段替代$project,该阶段只会覆盖你显式指定的字段,其余所有父文档字段会默认保留,不需要提前知晓父文档的全部字段结构。该方案同时满足上述两个约束条件,仅需指定需要保留的内嵌字段即可。
针对示例中stop字段可能是单个内嵌对象、也可能是内嵌对象数组的兼容写法如下:
db.bookmarks.aggregate([ { $addFields: { stop: { $cond: { // 判断stop是否为数组 if: { $isArray: "$stop" }, then: { // 是数组则遍历每个元素仅保留title字段 $map: { input: "$stop", in: { title: "$$this.title" } } }, // 不是数组则直接提取当前内嵌对象的title字段 else: { title: "$stop.title" } } } } } ])
执行结果
输出会保留所有父文档原有字段,同时仅保留内嵌stop字段中的title属性:
{ "_id" : 1, "user" : "1234", "stop" : { "title" : "book1" } } { "_id" : 2, "user" : "7890", "stop" : [ { "title" : "book2" }, { "title" : "book3" } ] }
原写法问题说明
之前使用$project阶段会丢失父字段的原因是:$project阶段只要显式指定了包含任意字段,除默认保留的_id字段外,所有未被显式指定包含的父字段都会被自动排除,不符合不需要提前知晓全量父字段的使用场景。
内容的提问来源于stack exchange,提问作者John Vottero
相关产品推荐
相关产品推荐

