Truy vấn đầu tiên của bạn đã đi đúng hướng khi bạn sử dụng sai toán tử đường ống.
Artist.native(function(err,collection) {
collection.aggregate(
[
{ "$project": {
"_id": 1,
"name": 1,
"total": { "$size": "$dubs" }
}}
],
function(err,result) {
if (err) return res.serverError(err);
console.log(result);
}
})
Tất nhiên, $ size
toán tử ở đó yêu cầu bạn cần có phiên bản MongoDB 2.6 hoặc cao hơn, điều này có thể bạn nên làm ngay bây giờ, nhưng bạn vẫn có thể làm điều tương tự mà không cần toán tử để đo độ dài mảng:
Artist.native(function(err,collection) {
collection.aggregate(
[
{ "$project": {
"_id": 1,
"name": 1,
"dubs": {
"$cond": [
{ "$eq": [ "$dubs", [] ] },
[0],
"$dubs"
]
}
}},
{ "$unwind": "$dubs" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"total": {
"$sum": {
"$cond": [
{ "$eq": [ "$dubs", 0 ] },
0,
1
]
}
}
}}
],
function(err,result) {
if (err) return res.serverError(err);
console.log(result);
}
})
Điều đó thực hiện tương tự bằng cách đếm các thành viên của mảng, nhưng thay vào đó, bạn cần $ unwind
các phần tử mảng để đếm chúng. Vì vậy, nó vẫn có thể được thực hiện nhưng không hiệu quả.
Ngoài ra, bạn cần xử lý các trường hợp mảng thực sự trống nhưng hiển thị do cách $ unwind
xử lý một mảng trống []
. Nếu không có nội dung thì tài liệu có chứa phần tử như vậy sẽ bị xóa khỏi kết quả. Theo cách tương tự, bạn sẽ cần sử dụng $ ifNull
để đặt một mảng trong đó tài liệu thậm chí không chứa phần tử cho $ unwind
để không gây ra lỗi.
Thực sự nếu bạn định thực hiện loại truy vấn này thường xuyên, thì bạn nên duy trì trường "tổng" trong tài liệu hơn là tìm cách tính toán nó trước. Sử dụng $ inc
toán tử cùng với các hoạt động như $ push
và $ pull
để kiểm đếm độ dài mảng hiện tại.
Điều đó hơi khác xa với triết lý Đường nước chung một chút, nhưng bạn đã giới thiệu các phép toán tổng hợp gốc và không còn quá nhiều thời gian để nhận ra rằng bạn đang có được hiệu suất tốt hơn từ việc sử dụng các phép toán gốc trong các lĩnh vực khác.
Vì vậy, với các tài liệu như sau:
{
"dubs": [{},{},{}],
"name": "The Doors",
"createdAt": "2014-12-15T15:24:26.216Z",
"updatedAt": "2014-12-15T15:24:26.216Z",
"id": "548efd2a436c850000353f4f"
},
{
"dubs": [],
"name": "The Beatles",
"createdAt": "2014-12-15T20:30:33.922Z",
"updatedAt": "2014-12-15T20:30:33.922Z",
"id": "548f44e90630d50000e2d61d"
}
Bạn nhận được chính xác kết quả bạn muốn trong từng trường hợp:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}