Wydaje się, że masz na myśli to, że chcesz „posortować” wyniki na podstawie „długości” tablicy „odpowiedzi”, a nie „właściwości” zwanej „długością”, jak sugeruje twoja składnia. Dla przypomnienia, ta składnia byłaby tutaj niemożliwa, ponieważ twój model jest "odwołany", co oznacza, że jedyne dane obecne w polu tablicy w dokumentach tej kolekcji to ObjectId
wartości tych dokumentów odniesienia.
Ale możesz to zrobić za pomocą .aggregate()
i $size
operator:
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
}
)
Potok agregacji działa etapami. Po pierwsze, istnieje $projekt
dla pól w wynikach, w których używasz $size
aby zwrócić długość określonej tablicy.
Teraz jest pole z "długością", etapy śledzisz za pomocą $sortuj
i $limit
które są stosowane jako własne etapy w potoku agregacji.
Lepszym rozwiązaniem byłoby zawsze zachowywanie właściwości length tablicy „odpowiedzi” w dokumencie. Ułatwia to sortowanie i wykonywanie zapytań bez innych operacji. Utrzymanie tego jest proste za pomocą $inc
operator jak ty $push
lub $pull
elementy z tablicy:
Question.findByIdAndUpdate(id,
{
"$push": { "answers": answerId },
"$inc": { "answerLength": 1 }
},
function(err,doc) {
}
)
Lub na odwrót podczas usuwania:
Question.findByIdAndUpdate(id,
{
"$pull": { "answers": answerId },
"$inc": { "answerLength": -1 }
},
function(err,doc) {
}
)
Nawet jeśli nie używasz operatorów atomowych, obowiązują te same zasady, gdy aktualizujesz „długość” w miarę postępów. Wtedy zapytanie z sortowaniem jest proste:
Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {
});
Ponieważ właściwość znajduje się już w dokumencie.
Więc zrób to za pomocą .aggregate()
bez zmian w danych lub zmień dane, aby zawsze uwzględniać długość jako właściwość, a Twoje zapytania będą bardzo szybkie.