如何在MongoDB中将子文档展平为根级别?

syg*_*syg 26 mongodb aggregation-framework

例如,如果我有这样的文档

{
  a: 1,
  subdoc: {
          b: 2,
          c: 3
          }
}
Run Code Online (Sandbox Code Playgroud)

如何将其转换为这样的格式?(不使用project)

{
  a: 1,
  b: 2,
  c: 3
}
Run Code Online (Sandbox Code Playgroud)

Amo*_*rni 28

您也可以使用MongoDB投影,即$project聚合框架管道运算符.(推荐方式).如果您不想使用,project请查看此链接

db.collection.aggregation([{$ project {.}}]);

以下是您案例的示例:

db.collectionName.aggregate
([
    { $project: { a: 1, 'b': '$subdoc.b', 'c': '$subdoc.c'} }
]);
Run Code Online (Sandbox Code Playgroud)

为您提供预期的输出,即

    {
        "a" : 1,
        "b" : 2,
        "c" : 3
    }
Run Code Online (Sandbox Code Playgroud)


chr*_*dam 14

您可以使用$replaceRoot一个$addFields阶段如下:

db.collection.aggregate([
    { "$addFields": { "subdoc.a": "$a" } },
    { "$replaceRoot": { "newRoot": "$subdoc" }  }
])
Run Code Online (Sandbox Code Playgroud)

  • 如果根目录有很多字段,则可以将 `mergeObjects` 与特殊变量 `$$ROOT` 一起使用,例如: `db.collection.aggregate([ {$replaceRoot: { newRoot: { $mergeObjects: ["$$ROOT] ", "$subdoc"] } } }, {$project: { subdoc: 0 } }, ])` (12认同)

sty*_*ane 14

我们可以使用$replaceWithfor$replaceRoot$mergeObjects运算符的别名来做到这一点。

let pipeline = [
   {
      "$replaceWith": {
         "$mergeObjects": [ { "a": "$a" }, "$subdoc" ]
      }
   }
];
Run Code Online (Sandbox Code Playgroud)

或者

let pipeline = [
    {
        "$replaceRoot": {
            "newRoot": {
                "$mergeObjects": [{ "a": "$a" }, "$subdoc" ]
            }
        }
    }
];

db.collection.aggregate(pipeline)
Run Code Online (Sandbox Code Playgroud)


小智 9

您还可以使用$$ROOT$mergeObjects

{ $replaceWith: {
        $mergeObjects: [ "$$ROOT", "$subdoc" ]
} }
Run Code Online (Sandbox Code Playgroud)


Nei*_*unn -1

您可以使用$set和来完成此操作$unset

db.collection.update({},{ $set: { "b": 2, "c": 3 }, $unset: { "subdoc": 1 } })
Run Code Online (Sandbox Code Playgroud)

当然,如果集合中有很多文档,那么就像上面一样,您需要循环集合文档才能获取值。MongoDB 无法单独在更新操作中引用字段的值:

db.collection.find({ "subdoc": {"$exists": 1 } }).forEach(function(doc) {
    var setDoc = {};
    for ( var k in doc.subdoc ) {
        setDoc[k] = doc.subdoc[k];
    }
    db.collection.update(
        { "_id": doc._id },
        { "$set": setDoc, "$unset": "subdoc" }
    );
})
Run Code Online (Sandbox Code Playgroud)

这还采用了一些安全用法,$exists以确保您选择的文档中“subdoc”键确实存在。