MongoDB - $project 嵌套文档到根级别

标签 mongodb

是否可以不写所​​有子文档的字段?

假设我有以下文档结构:

{
  field1: a,
  subdoc: {
          field2: b,
          field3: c
  }
}

我想使用 $project 来获取根级别的 suboc:

{
  field1: a,
  field2: b,
  field3: c              
}

这只是子文档中有2个字段的示例,我的真实文档有很多字段,将来可能会添加或删除更多字段,所以我希望$project动态而不是单独指定所有字段。

最佳答案

对于 MongoDB 3.6 及更新版本,使用带有 $replaceRoot 的聚合框架 可以与 $mergeObjects 一起应用的管道 运算符作为 newRoot 表达式。

这个表达式

{ "$mergeObjects": ["$subdoc", "$$ROOT"] }

将文档中的顶级字段与子文档嵌入字段中的字段合并,因此最终您的聚合操作将如下所示:

db.collection.aggregate([
    { "$replaceRoot": { 
        "newRoot": { 
            "$mergeObjects": [ "$subdoc", "$$ROOT" ] 
        } 
    } },
    { "$project": { "subdoc": 0 } }  
])

否则,您将需要一种机制来获取组装动态 $project 文档所需的所有动态 key 。这可以通过 Map-Reduce 实现。 。以下 mapreduce 操作将使用所有键作为 _id 值填充一个单独的集合:

mr = db.runCommand({
    "mapreduce": "my_collection",
    "map" : function() {
        for (var key in this.subdoc) { emit(key, null); }
    },
    "reduce" : function(key, stuff) { return null; }, 
    "out": "my_collection" + "_keys"
})

要获取所有动态键的列表,请在生成的集合上运行 distinct:

db[mr.result].distinct("_id")
["field2", "field3", ...]

现在给出上面的列表,您可以通过创建一个将在循环中设置其属性的对象来组装您的 $project 聚合管道文档。通常,您的 $project 文档将具有以下结构:

var project = {
    "$project": {
        "field1": 1,
        "field2": "$subdoc.field2",
        "field3": "$subdoc.field3"
    }
};

因此,使用上面的子文档键列表,您可以使用 JavaScript 的 reduce() 动态构造上面的内容方法:

var subdocKeys = db[mr.result].distinct("_id"),
    obj = subdocKeys.reduce(function (o, v){
      o[v] = "$subdoc." + v;
      return o;
    }, { "field1": 1 }),
    project = { "$project": obj };

db.collection.aggregate([project]);

关于MongoDB - $project 嵌套文档到根级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34431243/

相关文章:

linux - PHP升级到7后,为什么不能使用mongodb驱动?

javascript - Node.js 中 mongodb 数组的嵌套循环

mongodb - 什么样的数据不是关系型的?

mongodb - 复制/克隆 Mongoose 文档实例的最简单方法?

mongodb - mongodb mongo-go-driver Decimal128 中的高值和低值是多少以及如何使用它们创建新的小数

mongodb 3.4.3 Permission denied Wiredtiger_kv_engine.cpp 267 错误与 ubuntu 16

mongodb - MongoCollection.find() 是否搜索两次?

python - 如何从 Python 搜索 MongoDB ISODate 字段?

mongodb - 更新 MongoDB 中数组内数组内的嵌入对象

mongodb - mongodb 文档大小限制会从 16MB 增加吗?