MongoDB Aggregation Query- Rename Fields Returned from Within Embedded Documents

前端 未结 2 1967
闹比i
闹比i 2021-01-13 21:04

I\'m currently using aggregate operator to return documents that has an array of embedded (sub) documents. I want to rename the field name for the array and also rename fie

相关标签:
2条回答
  • 2021-01-13 21:26

    There are a couple of approaches to this, but it largely depends on your MongoDB version. More recent versions from 2.6 and upwards support the $map operator which you can use in $project to do what you want:

    db.friend.aggregate([
        { "$project": {
            "name": 1,
            "buddies": {
                "$map": {
                    "input": "$friends",
                    "as": "el",
                    "in": {
                        "nickName": "$$el.name",
                        "age": "$$el.age"
                    }
                }
            }
        }}
    ])
    

    In prior versions you would use $unwind to work with the array elements and re-construct via $group:

    db.collection.aggregate([
        { "$unwind": "$friends" },
        { "$group": {
            "_id": "$_id",
            "name": { "$first": "$name" },
            "buddies": {
                "$push": {
                    "nickName": "$friends.name",
                    "age": "$friends.age"
                }
            }
        }}
    ])
    

    With the first form being a little more efficient as you are not de-normalizing the array content and producing more documents in the pipeline to process.

    0 讨论(0)
  • 2021-01-13 21:37

    I think I figured it out the following aggregate query. I would be interested in if there is a better way of doing this.

    db.friends.aggregate([
        { $unwind: '$friends'},
        { $project: {
            _id: 1,
            name: 1,
            buddy: {
                nickName: '$friends.name',
                age: '$friends.age',
            }
        }},
        { $group: {        
            _id: '$_id',
            name: {'$first': '$name'},
            buddies: {"$push": "$buddy"}
        }}
    ]);
    

    Below I describe the response of each operator ($unwind, $project, $group)

    The $unwind would return something like this. It breaks out each Embedded Document into its own document. So where we had 1 document with 2 friends sub document, now we have two document. Both documents will have the same id and name fields but the friends sub document will be different:

    {
        "_id" : ObjectId("539c80d43cb9fe99d183a5f7"),
        "name" : "Matthew",
        "friends" : {"name" : "slim", "age" : "32"}
    }, {
        "_id" : : ObjectId("539c80d43cb9fe99d183a5f7"),,
        "name" : "Matthew",
        "friends" : {"name" : "buba", "age" : "36"}
    }
    

    The $project would return something like this. Here I'm creating a new Embedded Document called buddy and notice that I assigning "$friends.name" to "nickName":

    {
        "_id" : ObjectId("539c80d43cb9fe99d183a5f7"),
        "name" : "Matthew",
        "buddy" : {"nickName" : "slim","age" : "32"}
    }, {
        "_id" : : ObjectId("539c80d43cb9fe99d183a5f7"),,
        "name" : "Matthew",
        "friends" : {"nickName" : "buba","age" : "36"}
    }
    

    And then the $group would do something like this. Here I'm just group everything back together, but setting the array name to "buddies":

    {
        "_id" : ObjectId("539c80d43cb9fe99d183a5f7"),
        "name" : "Matthew",
        "buddies" : [
            {"nickName" : "slim","age" : "32"},
            {"nickName" : "buba","age" : "36"}
        ]
    }
    

    This seems to work, but if the friends array had duplicates, this process would remove the duplicates. This can be solved if there is a unique id for each friend.

    0 讨论(0)
提交回复
热议问题