MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

So sortieren Sie Dokumente basierend auf der Länge eines Array-Felds

Was Sie hier zu meinen scheinen, ist, dass Sie Ihre Ergebnisse basierend auf der "Länge" des Arrays "Antworten" "sortieren" möchten, anstatt einer "Eigenschaft" namens "Länge", wie Ihre Syntax impliziert. Fürs Protokoll, diese Syntax wäre hier nicht möglich, da Ihr Modell „referenziert“ ist, was bedeutet, dass die einzigen Daten, die im Array-Feld in den Dokumenten dieser Sammlung vorhanden sind, die ObjectId sind Werte dieser referenzierten Dokumente.

Aber Sie können dies mit .aggregate() -Methode und $size Betreiber:

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
    }
)

Eine Aggregationspipeline arbeitet stufenweise. Zuerst gibt es ein $project für die Felder in den Ergebnissen, wo Sie $size verwenden um die Länge des angegebenen Arrays zurückzugeben.

Nun gibt es ein Feld mit der „Länge“, den Stufen folgst du mit $sort und $limit die als eigene Stufen innerhalb einer Aggregationspipeline angewendet werden.

Ein besserer Ansatz wäre, die Längeneigenschaft Ihres Arrays "Antworten" immer innerhalb des Dokuments beizubehalten. Dies erleichtert das Sortieren und Abfragen ohne weitere Vorgänge. Die Wartung ist einfach mit $inc Operator wie Sie $push oder $pull Elemente aus dem Array:

Question.findByIdAndUpdate(id,
    {
        "$push": { "answers": answerId },
        "$inc": { "answerLength": 1 } 
    },
    function(err,doc) {

    }
)

Oder umgekehrt beim Entfernen:

Question.findByIdAndUpdate(id,
    {
        "$pull": { "answers": answerId },
        "$inc": { "answerLength": -1 } 
    },
    function(err,doc) {

    }
)

Auch wenn Sie die atomaren Operatoren nicht verwenden, gelten die gleichen Prinzipien, wenn Sie die "Länge" aktualisieren, während Sie fortfahren. Dann ist die Abfrage mit einer Sortierung einfach:

Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {

});

Da die Eigenschaft bereits im Dokument vorhanden ist.

Also entweder mit .aggregate() ohne Änderungen an Ihren Daten, oder ändern Sie Ihre Daten so, dass sie immer die Länge als Eigenschaft enthalten, und Ihre Abfragen werden sehr schnell sein.