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

时间:2014-04-07 04:51:13

标签: mongodb aggregation-framework

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

{
  a: 1,
  subdoc: {
          b: 2,
          c: 3
          }
}

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

{
  a: 1,
  b: 2,
  c: 3
}

8 个答案:

答案 0 :(得分:21)

您也可以使用MongoDB projection i.e $project aggregation framework pipeline operators(推荐方式)。如果您不想使用project,请查看此link

  

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

以下是您案例的示例:

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

按预期给出输出,即

    {
        "a" : 1,
        "b" : 2,
        "c" : 3
    }

答案 1 :(得分:12)

您可以将 $replaceRoot $addFields 阶段一起使用,如下所示:

db.collection.aggregate([
    { "$addFields": { "subdoc.a": "$a" } },
    { "$replaceRoot": { "newRoot": "$subdoc" }  }
])

答案 2 :(得分:2)

最好的方法是使用$replaceRoot$mergeObjects

let pipeline = [
    {
        "$replaceRoot":{
            "newRoot":{
                "$mergeObjects":[
                    {
                        "a":"$a"
                    },
                    "$subdoc"
                ]
            }
        }
    }
]
db.collection.aggregate(pipeline)

答案 3 :(得分:1)

如果要查询嵌套数组元素并在根级别显示 如果你有 2 个嵌套数组,你应该使用 $unwind 两次

db.mortgageRequests.aggregate( [
       { $unwind: "$arrayLevel1s" },
       { $unwind: "$arrayLevel1s.arrayLevel2s" },
       { $match: { "arrayLevel1s.arrayLevel2s.documentid" : { $eq: "6034bceead4ed2ce3951f38e" } } },
       { $replaceRoot: { newRoot: "$arrayLevel1s.arrayLevel2s" } }
    ] )

答案 4 :(得分:0)

您可以使用$set$unset

来执行此操作
db.collection.update({},{ $set: { "b": 2, "c": 3 }, $unset: { "subdoc": 1 } })

当然,如果集合中有很多文档,那么就像上面一样,你需要循环收集文档以获取值。 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" }
    );
})

这也使用$exists的一些安全用法,以确保您选择“subdoc”键实际存在的文档。

答案 5 :(得分:0)

我猜最简单的方法是使用map更改返回的结果。

collection.mapFunction = function(el) {
  el.b = el.subdoc.b;
  el.c = el.subdoc.c
  delete(el.subdoc);
  return el;
}

...

var result = await collection.aggregate(...).toArray();
result = result.map(collection.mapFunction);

答案 6 :(得分:0)

Mongo 4.2开始,$replaceWith聚合运算符可用于替换另一个文档(在我们的情况下为子文档),作为@提到的$replaceRoot的语法糖。 chridam。

因此,我们可以首先在子文档中包含根字段,以继续使用$set运算符(也在Mongo 4.2中引入,作为$addFields的别名),然后替换整个子文档使用$replaceWith

// { a: 1, subdoc: { b: 2, c: 3 } }
db.collection.aggregate([
  { $set: { "subdoc.a": "$a" } },
  { $replaceWith: "$subdoc" }
])
// { b: 2, c: 3, a: 1 }

答案 7 :(得分:0)

您也可以在 $$ROOT 中使用 $mergeObjects

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