MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Como classificar documentos com base no comprimento de um campo Array


O que você parece querer dizer aqui é que você deseja "classificar" seus resultados com base no "comprimento" da matriz "respostas", em vez de uma "propriedade" chamada "comprimento" como sua sintaxe indica. Para o registro, essa sintaxe seria impossível aqui, pois seu modelo é "referenciado", o que significa que os únicos dados presentes no campo de matriz nos documentos desta coleção são o ObjectId valores desses documentos referenciados.

Mas você pode fazer isso usando o .aggregate() e o $size operador:
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
    }
)

Um pipeline de agregação funciona em etapas. Primeiro, há um $project para os campos nos resultados, onde você usa $size para retornar o comprimento da matriz especificada.

Agora existe um campo com o "comprimento", você segue as etapas com $sort e $limit que são aplicados como seus próprios estágios em um pipeline de agregação.

Uma abordagem melhor seria sempre manter a propriedade length do seu array "answers" dentro do documento. Isso facilita a classificação e a consulta sem outras operações. Manter isso é simples usando o $inc operador como você $push ou $pull itens da matriz:
Question.findByIdAndUpdate(id,
    {
        "$push": { "answers": answerId },
        "$inc": { "answerLength": 1 } 
    },
    function(err,doc) {

    }
)

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

    }
)

Mesmo se você não estiver usando os operadores atômicos, os mesmos princípios se aplicam onde você atualiza o "comprimento" à medida que avança. Em seguida, consultar com uma classificação é simples:
Question.find().sort({ "answerLength": -1 }).limit(5).exec(function(err,result) {

});

Como a propriedade já está lá no documento.

Então faça isso com .aggregate() sem alterações em seus dados, ou altere seus dados para sempre incluir o comprimento como uma propriedade e suas consultas serão muito rápidas.