在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_COMPLETE
或UPDATE_COMPLETE
的{{1}}数组项。经过大量实验和阅读其他SO帖子后,我得到了以下内容:
db.cf_list_stacks.aggregate( {$match: {"StackSummaries.StackStatus": "CREATE_COMPLETE"}})
然而,这仍然会返回整个文档(我甚至不担心UPDATE_COMPLETE)。
我来自SQL背景,并且正在努力应对这样的简单查询。关于如何获取我正在寻找的信息的任何想法?
我看过的帖子:
更新
关于我在理解这个主题时学到的东西的注释:
答案 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
值的文档。