Cách "hiệu quả" nhất để làm điều này là bỏ qua $unwind
altogther và đơn giản là $group
để đếm. Về cơ bản, mảng "bộ lọc" nhận được $size
trong số các kết quả đến $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]
]
}
}
}
}}
])
Các bản phát hành trong tương lai của MongoDB sẽ có $filter
, điều này làm cho việc này trở nên đơn giản hơn nhiều:
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" ]
}
}
}
}
}
}}
])
Sử dụng $unwind
khiến các tài liệu không chuẩn hóa và tạo một bản sao trên mỗi mục nhập mảng một cách hiệu quả. Nếu có thể, bạn nên tránh điều này do chi phí thường rất cao. So sánh việc lọc và đếm các mục nhập mảng trên mỗi tài liệu nhanh hơn nhiều. Như là một $match
đơn giản và $group
đường ống so với nhiều giai đoạn.