MongoDB $ embedded document for root level

Using the aggregate conveyor, I try to project the embedded document to the root level WITHOUT projecting each field separately.

For example, I want to project namefrom this collection to the root level:

[
    {
        _id: "1",
        name: {
            firstName: "John",
            lastname: "Peters"
        }
    },
    {
        _id: "2",
        name: {
            firstName: "Mary",
            lastname: "Jones"
        }
    }
]

This is what I am looking for:

[
    {
        firstName: "John",
        lastname: "Peters"
    },
    {
        firstName: "Mary",
        lastname: "Jones"
    }
]

Is there a way to do this without projecting each field individually? I do not want to do this:

db.collection.aggregate(
    [
        {
            $project : {
                "_id" : 0,
                "firstName" : "$name.firstName",
                "lastName" : "$name.lastName"
            }
        }
    ]
+7
source share
4 answers

MongoDB 3.4 introduces a new stage in the aggregation pipeline - $replaceRootwhich does exactly what was set.

https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/

+5
source

, JavaScript.

# Set Object for what to project
var projectWhat = {'_id' : 0};

# Fill Object with keys
Object.keys(db.coll.findOne().name).forEach(function(x){
    projectWhat[x] = "$name." + x;
});

# Do Aggregate
db.coll.aggregate([{$project : projectWhat}])

{ "firstName" : "John", "lastname" : "Peters" }
{ "firstName" : "Mary", "lastname" : "Jones" }

, .

+2

This can be achieved by using $setto update all documents with values ​​in a sub-document name:

db.collection.find({ "name": {"$exists": 1 } }).forEach(function(doc) {
    var setName = {};
    for ( var k in doc.name ) {
        setName[k] = doc.name[k];
    }
    db.collection.update(
        { "_id": doc._id },
        { "$set": setName, "$unset": "name" }
    );
})

While I recommend using it $project, because it will be more effective than this solution, I can understand why you will not want to use it $project.

+1
source

Starting with Mongo 4.2, the aggregation operator can be used to replace a document with another (in our case, a subdocument): $replaceWith

// { _id: "1", name: { firstName: "John", lastname: "Peters" } }
// { _id: "2", name: { firstName: "Mary", lastname: "Jones"  } }
db.collection.aggregate({ $replaceWith: "$name" })
// { firstName: "John", lastname: "Peters" }
// { firstName: "Mary", lastname: "Jones" }
0
source

Source: https://habr.com/ru/post/1627187/


All Articles