Váš první dotaz byl na správné cestě, kdy jste použili nesprávný operátor potrubí.
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);
}
})
Samozřejmě $size
Operátor tam vyžaduje, abyste potřebovali verzi MongoDB 2.6 nebo vyšší, což byste už pravděpodobně měli udělat, ale stále můžete udělat to samé bez operátoru pro měření délky pole:
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);
}
})
To dělá totéž při počítání členů pole, ale místo toho byste museli $unwind
prvky pole, aby je bylo možné spočítat. Takže to lze stále provést, ale není to tak efektivní.
Navíc musíte zvládnout případy, kdy je pole skutečně prázdné, ale přítomné, protože $unwind
zpracovává prázdné pole []
. Pokud by neexistoval žádný obsah, pak by dokument obsahující takový prvek byl z výsledků odstraněn. Podobným způsobem byste museli použít $ ifNull
nastavit pole, kde dokument neobsahoval ani prvek pro $unwind
aby nedošlo k chybě.
Opravdu, pokud máte v úmyslu provádět tento druh dotazu pravidelně, měli byste v dokumentu udržovat pole "celkem" a ne se snažit jej nejprve vypočítat. Použijte $inc
operátor spolu s operacemi, jako je $push
a $pull
k udržení aktuální délky pole.
To se sice trochu vzdaluje od obecné filozofie Waterline, ale již jste zavedli nativní agregační operace a není to zase tak složité, abyste si uvědomili, že díky používání nativních operací také v jiných oblastech získáváte lepší výkon.
Takže s dokumenty, jako jsou tyto:
{
"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"
}
V každém případě získáte přesně požadované výsledky:
{
"_id" : ObjectId("5494b79d7e22da84d53c8760"),
"name" : "The Doors",
"total" : 3
},
{
"_id" : ObjectId("5494b79d7e22da84d53c8761"),
"name" : "The Beatles",
"total" : 0
}