Der "leistungsfähigste" Weg, dies zu tun, besteht darin, $unwind
zu überspringen insgesamt und einfach $group
zählen. Im Wesentlichen erhalten "Filter"-Arrays die $size
der Ergebnisse zu $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]
]
}
}
}
}}
])
Zukünftige Versionen von MongoDB werden $filter
haben , was dies viel einfacher macht:
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" ]
}
}
}
}
}
}}
])
Verwenden von $unwind
bewirkt, dass die Dokumente denormalisiert werden, und erstellt effektiv eine Kopie pro Array-Eintrag. Aufgrund der oft extremen Kosten sollten Sie dies nach Möglichkeit vermeiden. Das Filtern und Zählen von Array-Einträgen pro Dokument ist im Vergleich viel schneller. Genauso wie ein einfaches $match
und $group
Pipeline im Vergleich zu vielen Stufen.