如何在MongoDB中检索子文档数组

时间:2014-06-06 08:36:44

标签: mongodb python-2.7 mongodb-query aggregation-framework

我在mongodb有一个这样的集合:

 db.country_list.find().pretty()
{
"_id" : ObjectId("53917321ccbc96175d7a808b"),
"countries" : [
    {
        "countryName" : "Afghanistan",
        "iso3" : "AFG",
        "callingCode" : "93"
    },
    {
        "countryName" : "Aland Islands",
        "iso3" : "ALA",
        "callingCode" : "358"
    },
    {
        "countryName" : "Albania",
        "iso3" : "ALB",
        "callingCode" : "355"
    }
              ]
}

就像我有100个国家/地区的详细信息

我想检索调用代码为355的国家/地区名称。 我试过这样的

db.country_list.find({countries: {$elemMatch :{ 'callingCode':'355'} } } )

并且喜欢这个

 db.country_list.find({'countries.callingCode':'355'}).pretty()

但我得到了所有记录。如何获得特定记录。谢谢提前

1 个答案:

答案 0 :(得分:1)

您想要的是positional $运算符:

db.country_list.find(
   { "countries": { "$elemMatch" :{ "callingCode":"355"} } }
   { "countries.$": 1 }
)

或者甚至使用您尝试过的其他语法:

db.country_list.find(
   { "countries.callingCode": "355"}
   { "countries.$": 1 }
)

这是因为“查询”与文档匹配,并且不是这些文档中包含包含的数组的过滤器。因此,第二个参数将字段与查询端匹配的“位置”进行投影。

如果您需要匹配多个数组元素,那么您可以使用具有更大灵活性的聚合框架:

db.country_list.aggregate([

    // Matches the documents that "contain" the match
    { "$match": {
        "countries.callingCode": "355"
    }},

    // Unwind the array to de-normalize as documents
    { "$unwind": "$countries" },

    // Match to "filter" the array content
    { "$match": {
        "countries.callingCode": "355"
    }},

    // Group back if you want an array
    { "$group": {
        "_id": "$_id",
        "countries": { "$push": "$countries" }
    }}
])

或者使用MongoDB 2.6或更高版本,您可以在没有 $unwind $group 的情况下执行此操作:

db.country_list.aggregate([

    // Matches the documents that "contain" the match
    { "$match": {
        "countries.callingCode": "355"
    }},

    // Project with "$map" to filter
    { "$project": {
        "countries": {
            "$setDifference": [
                { "$map": {
                    "input": "$countries",
                    "as": "el",
                    "in": { 
                        "$cond": [
                            { "$eq": [ "$$el.callingCode", "355" ] }
                            "$$el",
                            false
                        ]
                    }
                }},
                [false]
            ]
        }
    }}

])