MongoDB聚合查询 - 重命名嵌入式文档中返回的字段

时间:2014-09-10 03:38:42

标签: mongodb mongodb-query aggregation-framework

我目前正在使用聚合运算符来返回包含嵌入(子)文档数组的文档。我想重命名数组的字段名称,并重命名数组的嵌入文档中的字段名称。

作为一个例子,对于投影,我想重命名数组来自"朋友"和#34;好友"我还想重命名嵌入式文档中的字段" name" to" nickName"。我可以在集合操作中执行此操作吗?如果是,如何操作?

以下是源文档的示例:

[
    {
        _id: ObjectID,
        name: 'Matthew',
        friends: [
            {name: 'Slim', age: '32'},
            {name: 'buba', age: '36'}
        ]
    }
]

这里的结果应该是什么样的:

[
    {
        _id: ObjectID,
        name: 'Matthew',
        buddies: [
            {nickName: 'Chris', age: '32'},
            {nickName: 'Jim', age: '36'}
        ]
    }
]

感谢您的帮助。

2 个答案:

答案 0 :(得分:8)

有两种方法可以解决这个问题,但这在很大程度上取决于您的MongoDB版本。 2.6及更高版本的更新版本支持$map运算符,您可以在$project中使用它来执行您想要的操作:

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

在以前的版本中,您可以使用$unwind来处理数组元素并通过$group重新构建:

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

第一种形式的效率要高一些,因为您没有对数组内容进行反规范化并在管道中生成更多文档来处理。

答案 1 :(得分:1)

我想我想出了以下聚合查询。如果有更好的方法,我会感兴趣。

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"}
    }}
]);

下面我描述每个运营商的响应($ unwind,$ project,$ group)

$ unwind会返回这样的东西。它将每个嵌入式文档分解为自己的文档。那么我们在哪里有1个文件和2个朋友子文件,现在我们有两个文件。两个文档将具有相同的id和name字段,但friends子文档将是不同的:

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

$ project会返回这样的东西。在这里,我正在创建一个名为buddy的新嵌入式文档,并注意到我将“$ friends.name”分配给“nickName”:

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

然后$ group会做这样的事情。在这里,我只是将所有内容组合在一起,但将数组名称设置为“好友”:

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

这似乎有效,但如果friends数组有重复项,则此过程将删除重复项。如果每个朋友都有唯一的ID,则可以解决此问题。