MongoDB - 使用查询提取嵌入文档

时间:2015-10-07 10:10:26

标签: mongodb embedded-documents

我有一个包含如下文档的集合:

{
    name: "Johann",
    surname: "Esburg",
    jobs: [
       {
           "profession": "chef",
           "salary": 1000
       }, {
           "profession": "gardener",
           "salary": 800
       }
    ]
},
{
    name: "Sam",
    surname: "Sonite",
    jobs: [
       {
           "profession": "doctor",
           "salary": 2000
       }, {
           "profession": "barber",
           "salary": 850
       }
    ]
}

我想找到工资大于900的所有工作,结果是:

[
    {
        "profession": "chef",
        "salary": 1000
    }, {
        "profession": "doctor",
        "salary": 2000
    }
]

我很确定我必须求助于mongodb aggregation。我设法达到的最好成绩是:

db.persons.aggregate([
    {$unwind: "$jobs"},
    {$match: {"jobs.salary": {$gt: 900}}},
    {$project: {jobs: 1, _id: 0}}])

返回:

[
    {
        "jobs": {
            "profession": "chef",
            "salary": 1000
         }
    },
    {
        "jobs": {
            "profession": "doctor",
            "salary": 2000
        }
    }
]

但这不是我想要的。我还希望删除jobs密钥。 我知道有一种可能性是在projection中指定嵌入文档的每个变量,如下所示:

db.persons.aggregate([
    {$unwind: "$jobs"},
    {$match: {"jobs.salary": {$gt: 900}}},
    {$project:
        {"profession": "$jobs.profession",
         "salary": "$jobs.salary", _id: 0}}])

但我宁愿避免使用它,因为嵌入的文档在某些字段上可能会有所不同。

1 个答案:

答案 0 :(得分:0)

考虑以下聚合管道操作, $match 管道,因为第一步是确保高效操作所必需的,因为聚合可以使用索引以及查询集合以最小化进入管道的文档数量:

db.persons.aggregate([
    {
        "$match": {
            "jobs.salary": { "$gt": 900 }
        }
    },
    {
        "$unwind": "$jobs"
    }, 
    {
        "$match": {
            "jobs.salary": { "$gt": 900 }
        }
    },   
    {
        "$group": { 
            "_id": null,
            "jobs": {
                "$push": {
                    "profession": "$jobs.profession",
                    "salary": "$jobs.salary"
                }
            }
        }
    },
    {
        "$unwind": "$jobs"
    },
    {
        "$project": {
            "_id": 0, "profession": "$jobs.profession", "salary": "$jobs.salary"
        }
    }
])

示例输出:

/* 0 */
{
    "result" : [ 
        {
            "profession" : "chef",
            "salary" : 1000
        }, 
        {
            "profession" : "doctor",
            "salary" : 2000
        }
    ],
    "ok" : 1
}