MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Come ordinare i documenti in base alla lunghezza di un campo Array

Quello che sembra voler dire qui è che vuoi "ordinare" i tuoi risultati in base alla "lunghezza" dell'array "risposte", piuttosto che a una "proprietà" chiamata "lunghezza" come implica la tua sintassi. Per la cronaca, quella sintassi sarebbe impossibile qui poiché il tuo modello è "referenziato", il che significa che gli unici dati presenti all'interno del campo dell'array nei documenti di questa raccolta sono ObjectId valori di quei documenti di riferimento.

Ma puoi farlo usando .aggregate() metodo e il $size operatore:

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

Una pipeline di aggregazione funziona in più fasi. Innanzitutto, esiste un $project per i campi nei risultati, dove usi $size per restituire la lunghezza dell'array specificato.

Ora c'è un campo con la "lunghezza", segui le fasi con $sort e $limit che vengono applicati come fasi proprie all'interno di una pipeline di aggregazione.

Un approccio migliore sarebbe quello di mantenere sempre la proprietà della lunghezza dell'array "risposte" all'interno del documento. Ciò semplifica l'ordinamento e le query senza altre operazioni. Mantenerlo è semplice utilizzando $inc operatore come te $push o $pull elementi dall'array:

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

    }
)

O viceversa durante la rimozione:

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

    }
)

Anche se non stai usando gli operatori atomici, si applicano gli stessi principi quando aggiorni la "lunghezza" man mano che procedi. Quindi eseguire query con un ordinamento è semplice:

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

});

Poiché la proprietà è già presente nel documento.

Quindi fallo con .aggregate() senza modifiche ai tuoi dati o modifica i tuoi dati per includere sempre la lunghezza come proprietà e le tue query saranno molto veloci.