Kueri pertama Anda berada di jalur yang benar karena Anda menggunakan operator saluran yang salah.
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);
}
})
Tentu saja $size
operator di sana mengharuskan Anda memerlukan MongoDB 2.6 atau versi yang lebih baru, yang mungkin harus Anda lakukan sekarang, tetapi Anda masih dapat melakukan hal yang sama tanpa operator untuk mengukur panjang larik:
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);
}
})
Itu melakukan hal yang sama dengan menghitung anggota array, tetapi sebaliknya Anda harus $unwind
elemen array untuk menghitungnya. Jadi masih bisa dilakukan tapi kurang efisien.
Selain itu, Anda perlu menangani kasus di mana array benar-benar kosong tetapi ada karena cara $unwind
memperlakukan array kosong []
. Jika tidak ada konten maka dokumen yang mengandung elemen tersebut akan dihapus dari hasil. Dengan cara yang sama, Anda perlu menggunakan $ifNull
untuk menyetel larik di mana dokumen bahkan tidak mengandung elemen untuk $unwind
untuk tidak menghasilkan kesalahan.
Sungguh jika Anda berniat melakukan kueri semacam ini secara teratur, maka Anda harus mempertahankan bidang "total" dalam dokumen daripada berusaha menghitungnya terlebih dahulu. Gunakan $inc
operator bersama dengan operasi seperti $push
dan $pull
untuk menghitung panjang larik saat ini.
Itu sedikit menyimpang dari filosofi Waterline umum, tetapi Anda telah memperkenalkan operasi agregasi asli dan tidak terlalu sulit untuk menyadari bahwa Anda mendapatkan kinerja yang lebih baik dari menggunakan operasi asli di area lain juga.
Jadi dengan dokumen seperti ini:
{
"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"
}
Anda mendapatkan hasil yang Anda inginkan dalam setiap kasus:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}