Vad du verkar mena här är att du vill "sortera" dina resultat baserat på "längden" på "svars"-matrisen, snarare än en "egenskap" som kallas "längd" som din syntax antyder. För att ta reda på, skulle den syntaxen vara omöjlig här eftersom din modell är "referenserad", vilket innebär att den enda data som finns i arrayfältet i dokumenten i denna samling är ObjectId
värden för dessa refererade dokument.
Men du kan göra detta med .aggregate()
metoden och $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 fungerar i etapper. Först finns det ett $projekt
för fälten i resultaten, där du använder $size
för att returnera längden på den angivna arrayen.
Nu finns det ett fält med "längden", du följer stegen med $sort
och $limit
som tillämpas som sina egna steg inom en aggregeringspipeline.
Ett bättre tillvägagångssätt skulle vara att alltid behålla egenskapen length för din "svars"-array i dokumentet. Detta gör det enkelt att sortera och fråga på utan andra operationer. Att underhålla detta är enkelt med $inc
operatör som du $push
eller $pull
objekt från arrayen:
Question.findByIdAndUpdate(id,
{
"$push": { "answers": answerId },
"$inc": { "answerLength": 1 }
},
function(err,doc) {
}
)
Eller tvärtom när du tar bort:
Question.findByIdAndUpdate(id,
{
"$pull": { "answers": answerId },
"$inc": { "answerLength": -1 }
},
function(err,doc) {
}
)
Även om du inte använder atomoperatorerna så gäller samma principer där du uppdaterar "längden" allt eftersom. Sedan är det enkelt att fråga med en sortering:
Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {
});
Eftersom fastigheten redan finns i dokumentet.
Så gör det antingen med .aggregate()
utan ändringar av din data, eller ändra din data så att den alltid inkluderar längden som en egenskap och dina frågor kommer att vara mycket snabba.