如何在mongodb查询中过滤数组

时间:2015-05-13 06:14:16

标签: mongodb

在mongodb中,我有一个包含单个文档的集合,如下所示:

{ 
    "_id" : ObjectId("5552b7fd9e8c7572e36e39df"), 
    "StackSummaries" : [
        {
            "StackId" : "arn:aws:cloudformation:ap-southeast-2:406119630047:stack/XXXX-30fb22a-285-439ee279-c7c8d36/4ebd8770-f8f4-11e4-bf36-503f2370240f", 
            "TemplateDescription" : "XXXX", 
            "StackStatusReason" : "", 
            "CreationTime" : "2015-05-12T22:14:50.535Z", 
            "StackName" : "XXXX", 
            "StackStatus" : "CREATE_COMPLETE"
        }, 
        {
            "TemplateDescription" : "XXXX", 
            "StackStatusReason" : "", 
            "CreationTime" : "2015-05-11T04:02:05.543Z", 
            "StackName" : "XXXX", 
            "StackStatus" : "DELETE_COMPLETE", 
            "StackId" : "arn:aws:cloudformation:ap-southeast-2:406119630047:stack/XXXXX/7c8d04e0-f792-11e4-bb12-506726f15f9a"
        },
        { ... },
        { many others }
    ]
}

aws cli 命令导入的结果aws cloudformation list-stacks

我试图找到StackSummaries StackStatus CREATE_COMPLETEUPDATE_COMPLETE的{​​{1}}数组项。经过大量实验和阅读其他SO帖子后,我得到了以下内容:

db.cf_list_stacks.aggregate( {$match: {"StackSummaries.StackStatus": "CREATE_COMPLETE"}})

然而,这仍然会返回整个文档(我甚至不担心UPDATE_COMPLETE)。

我来自SQL背景,并且正在努力应对这样的简单查询。关于如何获取我正在寻找的信息的任何想法?

我看过的帖子:

更新

关于我在理解这个主题时学到的东西的注释:

  • aggregate()只是一个管道(就像Unix shell管道一样),其中每个$运算符只是另一个步骤。和shell管道一样,它们看起来很复杂,但是你只需要逐步构建它们,直到得到你想要的结果。
  • Mongo有一个很棒的网络研讨会:Exploring the Aggregation Framework
  • RoboMongo是处理Mongo数据和查询的好工具(GPL3)

2 个答案:

答案 0 :(得分:4)

如果您只想要StackSummaries数组中的对象,则应使用$unwind子句展开数组,过滤所需的文档,然后仅投影实际需要的文档部分。

查询看起来像这样:

db.cf_list_stacks.aggregate([
    { '$unwind' : '$StackSummaries' },
    { '$match' : { 'StackSummaries.StackStatus' : 'CREATE_COMPLETE' } },
    { '$project' : { 
         'TemplateDescription' : '$StackSummaries.TemplateDescription',
         'StackStatusReason' : '$StackSummaries.StackStatusReason',
         ...
    } }
])

有用的链接:

答案 1 :(得分:1)

使用MongoDB 3.4及更新版本,您可以利用$addFields $filter aggregation framework 运算符来获得所需的结果。

考虑运行以下管道:

db.cf_list_stacks.aggregate([
    {
        "$addFields": {
            "StackSummaries": {
                "$filter": {
                    "input": "$StackSummaries",
                    "as": "el":
                    "cond": {
                        "$in": [ 
                            "$$el.StackStatus", 
                            ["CREATE_COMPLETE", "UPDATE_COMPLETE"] 
                        ] 
                    }
                }
            }
        }
    }
]);

对于MongoDB 3.2

db.cf_list_stacks.aggregate([
    {
        "$project": {
            "StackSummaries": {
                "$filter": {
                    "input": "$StackSummaries",
                    "as": "el":
                    "cond": {
                        "$or": [
                            { "$eq": ["$$el.StackStatus", "CREATE_COMPLETE"] },
                            { "$eq": ["$$el.StackStatus", "UPDATE_COMPLETE"] }
                        ]
                    }
                }
            }
        }
    }
]);

对于MongoDB 3.0及以下

db.cf_list_stacks.aggregate([
    { "$unwind": "$StackSummaries" },
    {
        "$match": {            
            "StackSummaries.StackStatus": {
                "$in": ["CREATE_COMPLETE", "UPDATE_COMPLETE"]
            }
        }        
    },
    {
        "$group": {
            "_id": "$_id",
            "StackSummaries": {
                "$addToSet": "$StackSummaries"
            }
        }
    }
])

上面的管道有$unwind运算符,它从输入文档中解构StackSummaries数组字段,为每个元素输出一个文档。每个输出文档都使用元素值替换数组。

$unwind之后需要进一步过滤才能获得通过给定条件的文档,因此接下来会有第二个$match运算符管道阶段。

为了在执行$unwind位后获取原始数组字段,您需要使用$group运算符对文档进行分组,然后在组中使用$addToSet数组运算符然后将元素推入数组。

根据您尝试查找StackSummaries数组StackStatus CREATE_COMPLETE UPDATE_COMPLETE的项目的标准,您可以使用$elemMatch projection,但这不能与$in运算符一起使用,以获取StackStatus CREATE_COMPLETE {的文档{1}}此时此刻。对此有一个 JIRA 问题:

UPDATE_COMPLETE

这只会为您提供db.cf_list_stacks.find( { "StackSummaries.StackStatus": { "$in": ["CREATE_COMPLETE", "UPDATE_COMPLETE"] } }, { "StackSummaries": { "$elemMatch": { "StackStatus": { "$in": ["CREATE_COMPLETE", "UPDATE_COMPLETE"] } } } }) 具有StackStatus值的文档。