Hvad du synes at mene her er, at du vil "sortere" dine resultater baseret på "længden" af "svar"-arrayet, snarere end en "egenskab" kaldet "længde", som din syntaks antyder. For en god ordens skyld ville den syntaks være umulig her, da din model er "refereret", hvilket betyder, at de eneste data, der findes i array-feltet i dokumenterne i denne samling, er ObjectId
værdierne af disse refererede dokumenter.
Men du kan gøre dette ved at bruge .aggregate()
metoden og $size
operatør:
Question.aggregate(
[
{ "$project": {
"title": 1,
"content": 1,
"created": 1,
"updated": 1,
"author": 1,
"answers": 1,
"length": { "$size": "$answers" }
}},
{ "$sort": { "length": -1 } },
{ "$limit": 5 }
],
function(err,results) {
// results in here
}
)
En aggregeringspipeline fungerer i etaper. For det første er der et $projekt
for felterne i resultaterne, hvor du bruger $size
for at returnere længden af det angivne array.
Nu er der et felt med "længden", du følger etaperne med $sort
og $limit
som anvendes som deres egne stadier i en aggregeringspipeline.
En bedre tilgang ville være altid at opretholde længdeegenskaben for dit "svar"-array i dokumentet. Dette gør det nemt at sortere og forespørge på uden andre handlinger. Det er nemt at vedligeholde dette ved at bruge $inc
operatør som du $push
eller $pull
elementer fra arrayet:
Question.findByIdAndUpdate(id,
{
"$push": { "answers": answerId },
"$inc": { "answerLength": 1 }
},
function(err,doc) {
}
)
Eller omvendt, når du fjerner:
Question.findByIdAndUpdate(id,
{
"$pull": { "answers": answerId },
"$inc": { "answerLength": -1 }
},
function(err,doc) {
}
)
Selvom du ikke bruger atomoperatorerne, så gælder de samme principper, hvor du opdaterer "længden" efterhånden. Så er det nemt at forespørge med en sortering:
Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {
});
Da ejendommen allerede er der i dokumentet.
Så gør det enten med .aggregate()
uden ændringer af dine data, eller ændre dine data til altid at inkludere længden som en egenskab, og dine forespørgsler vil være meget hurtige.