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.