Twoje pierwsze zapytanie było na właściwej ścieżce, kiedy użyłeś niewłaściwego operatora potoku.
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);
}
})
Oczywiście $size
Operator tam wymaga, że potrzebujesz MongoDB 2.6 lub nowszej wersji, co prawdopodobnie powinieneś zrobić do tej pory, ale nadal możesz zrobić to samo bez operatora do pomiaru długości tablicy:
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);
}
})
Robi to to samo, licząc członków tablicy, ale zamiast tego musisz $rozwiń
elementy tablicy w celu ich zliczenia. Więc nadal można to zrobić, ale nie jest tak wydajne.
Dodatkowo musisz poradzić sobie z przypadkami, w których tablica jest naprawdę pusta, ale jest obecna, ponieważ $rozwiń
traktuje pustą tablicę []
. Gdyby nie było treści, dokument zawierający taki element zostałby usunięty z wyników. W podobny sposób musisz użyć $ ifNull
aby ustawić tablicę, w której dokument nie zawierał nawet elementu dla $odpręż
aby nie powodować błędu.
Naprawdę, jeśli zamierzasz wykonywać tego rodzaju zapytania regularnie, powinieneś zachować w dokumencie pole „total”, zamiast starać się je najpierw obliczyć. Użyj $inc
operator wraz z operacjami takimi jak $push
i $pull
aby zliczać bieżącą długość tablicy.
To trochę odbiega od ogólnej filozofii Waterline, ale wprowadziłeś już natywne operacje agregacji i nie jest to zbyt trudne, aby zdać sobie sprawę, że uzyskujesz lepszą wydajność dzięki używaniu natywnych operacji również w innych obszarach.
Tak więc z dokumentami takimi jak te:
{
"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"
}
W każdym przypadku uzyskujesz dokładnie takie wyniki, jakich oczekujesz:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}