Edg*_*nez 3 mongodb mongodb-query aggregation-framework
我有这样的文档结构
[{
name: "Something",
codes: [
{type: 11},
{type: 11},
{type: 15}
]
},
{
name: "Another",
codes: [
{type: 11},
{type: 12},
{type: 15},
{type: 11}
]
}]]
Run Code Online (Sandbox Code Playgroud)
我需要计算type = 11集合中每个条目出现的次数.我很难过.
虽然$match可以应用仅过滤掉包含特定类型代码的文档,但不应将其应用于此特定问题陈述.因为它会从输出中过滤掉没有特定类型代码的文档.
你需要:
Unwind 每个文档都基于代码字段.project字段wantedType具有值1
或具有值0.Group通过该_id字段获取字段的总和wantedType,该字段为您提供特定文档中所需类型代码的数量.0显示为其计数.码:
var typeCountToCalculate = 11;
db.collection.aggregate([
{$unwind:"$codes"},
{$project:{"name":1,
"wantedType":{$cond:[{$eq:["$codes.type",typeCountToCalculate ]},1,0]}}},
{$group:{"_id":"$_id",
"name":{$first:"$name"},"count":{$sum:"$wantedType"}}}
])
Run Code Online (Sandbox Code Playgroud)
O/P:
{
"_id" : ObjectId("54ad79dae024832588b287f4"),
"name" : "Another",
"count" : 2
}
{
"_id" : ObjectId("54ad79dae024832588b287f3"),
"name" : "Something",
"count" : 2
}
Run Code Online (Sandbox Code Playgroud)
MongoDB的聚合框架就是这里的答案。关键操作$unwind用于将数组内容处理为“规范化”文档,以及$group用于获得计数的管道阶段。
$match流水线阶段还进行了优化。在查询开始时是为了过滤掉可能不匹配的文档,在$unwind阶段之后,都是为了删除那些肯定不符合条件的元素(现在是document):
db.collection.aggregate([
// Match to filter documents
{ "$match": { "codes.type": 11 }},
// Unwind to 'de-normalize'
{ "$unwind": "$codes" },
// Match to filter again, but remove the array elements
{ "$match": { "codes.type": 11 }},
// Count the occurrences of the the matches
{ "$group": {
"_id": "$codes.type",
"count": { "$sum": 1 }
}}
])
Run Code Online (Sandbox Code Playgroud)
自然地,如果您抽出所有“匹配项”,那么整个集合中每个“类型”都会获得“计数”。
在现代版本中,您可以使用$redactMongoDB 2.6及更高版本的运算符对此进行一些更改。如果由于此管道阶段的递归性质而有所不为:
db.collection.aggregate([
// Match to filter documents
{ "$match": { "codes.type": 11 }},
// Filter out non matches
{ "$redact": {
"$cond": {
"if": { "$eq": [
{ "$ifNull": [ "$type", 11 ] },
11
]},
"then": "$$DESCEND",
"else": "$$PRUNE"
}
}}
// Unwind to 'de-normalize'
{ "$unwind": "$codes" },
// Count the occurrences of the the matches
{ "$group": {
"_id": "$codes.type",
"count": { "$sum": 1 }
}}
)
Run Code Online (Sandbox Code Playgroud)
这是一种不同的过滤方式,如果您的服务器支持,则完全有效。如果在其他带有嵌套级别的示例中使用,请小心。
在执行任何其他操作之前,请始终过滤要在“ first”上使用的匹配值。这消除了在聚合管道中处理不必要的工作。如果只有10,000个可能的匹配项,并且这些文档中只有2,000个元素也匹配,则不会处理100,000个文档。
| 归档时间: |
|
| 查看次数: |
1257 次 |
| 最近记录: |