sql >> Base de Datos >  >> NoSQL >> MongoDB

Cómo ordenar documentos según la longitud de un campo de matriz

Lo que parece querer decir aquí es que desea "ordenar" sus resultados en función de la "longitud" de la matriz de "respuestas", en lugar de una "propiedad" llamada "longitud" como implica su sintaxis. Para el registro, esa sintaxis sería imposible aquí ya que su modelo está "referenciado", lo que significa que los únicos datos presentes dentro del campo de matriz en los documentos de esta colección son el ObjectId valores de esos documentos referenciados.

Pero puede hacer esto usando el .aggregate() y el $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
    }
)

Una canalización de agregación funciona por etapas. Primero, hay un $project para los campos en los resultados, donde usa $size para devolver la longitud de la matriz especificada.

Ahora hay un campo con la "longitud", sigues las etapas con $sort y $limit que se aplican como sus propias etapas dentro de una canalización de agregación.

Un mejor enfoque sería mantener siempre la propiedad de longitud de su matriz de "respuestas" dentro del documento. Esto facilita la clasificación y la consulta sin otras operaciones. Mantener esto es simple usando $inc operador como tú $push o $pull elementos de la matriz:

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

    }
)

O al revés al eliminar:

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

    }
)

Incluso si no está utilizando los operadores atómicos, se aplican los mismos principios cuando actualiza la "longitud" a medida que avanza. Entonces consultar con una clasificación es simple:

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

});

Como la propiedad ya está en el documento.

Así que hazlo con .aggregate() sin cambios en sus datos, o cambie sus datos para incluir siempre la longitud como propiedad y sus consultas serán muy rápidas.