Det mest "presterande" sättet att göra detta är att hoppa över $unwind helt enkelt och helt enkelt $group att räkna. I huvudsak får "filter"-arrayer $size av resultaten till $sum :
db.objects.aggregate([
{ "$match": {
"createddate": {
"$gte": ISODate("2015-08-30T00:00:00.000Z")
},
"activity.action": "test_action"
}},
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$size": {
"$setDifference": [
{ "$map": {
"input": "$activity",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.action", "test_action" ] },
"$$el",
false
]
}
}},
[false]
]
}
}
}
}}
])
Framtida versioner av MongoDB kommer att ha $filter , vilket gör detta mycket enklare:
db.objects.aggregate([
{ "$match": {
"createddate": {
"$gte": ISODate("2015-08-30T00:00:00.000Z")
},
"activity.action": "test_action"
}},
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$size": {
"$filter": {
"input": "$activity",
"as": "el",
"cond": {
"$eq": [ "$$el.action", "test_action" ]
}
}
}
}
}
}}
])
Använder $unwind gör att dokumenten avnormaliseras och skapar effektivt en kopia per arraypost. Om möjligt bör du undvika detta på grund av den ofta extrema kostnaden. Filtrering och räkning av arrayposter per dokument är mycket snabbare i jämförelse. Liksom en enkel $match och $group pipeline jämfört med många stadier.