Uw eerste vraag was op het goede spoor, u gebruikte de verkeerde pijpleidingoperator.
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);
}
})
Natuurlijk de $size
operator daar vereist dat je een MongoDB 2.6 of hogere versie nodig hebt, wat je nu waarschijnlijk zou moeten doen, maar je kunt nog steeds hetzelfde doen zonder de operator voor het meten van de arraylengte:
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);
}
})
Dat doet hetzelfde door de leden van de array te tellen, maar in plaats daarvan moet je $unwind
de array-elementen om ze te tellen. Het kan dus nog steeds worden gedaan, maar is niet zo efficiënt.
Bovendien moet u de gevallen behandelen waarin de array echt leeg is maar aanwezig is vanwege de manier waarop $unwind
behandelt een lege array []
. Als er geen inhoud was, zou het document dat een dergelijk element bevatte uit de resultaten worden verwijderd. Op een vergelijkbare manier zou u $ifNull
om een array in te stellen waarin het document niet eens een element bevat voor $unwind
om niet tot een fout te leiden.
Als u van plan bent dit soort zoekopdrachten regelmatig uit te voeren, moet u een "totaal"-veld in het document behouden in plaats van het eerst te berekenen. Gebruik de $inc
operator samen met bewerkingen zoals $push
en $pull
om de huidige arraylengte bij te houden.
Dat wijkt een beetje af van de algemene Waterline-filosofie, maar je hebt al native aggregatiebewerkingen geïntroduceerd en het is niet zo moeilijk om te beseffen dat je ook betere prestaties krijgt door native bewerkingen in andere gebieden te gebruiken.
Dus met documenten als deze:
{
"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"
}
U krijgt in elk geval precies de resultaten die u wilt:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}