Den mest "performante" måde at gøre dette på er at springe $unwind
over alt sammen og blot $group
at tælle. Grundlæggende får "filter"-arrays $size
af resultaterne til $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]
]
}
}
}
}}
])
Fremtidige udgivelser af MongoDB vil have $filter
, hvilket gør dette meget mere enkelt:
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" ]
}
}
}
}
}
}}
])
Bruger $unwind
får dokumenterne til at denormalisere og skaber effektivt en kopi pr. array-indgang. Hvor det er muligt, bør du undgå dette på grund af de ofte ekstreme omkostninger. Filtrering og optælling af matrixposter pr. dokument er meget hurtigere i sammenligning. Som er en simpel $match
og $group
pipeline sammenlignet med mange faser.