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

Devuelve el último valor verdadero para cada grupo

La mejor manera de hacer esto es usando el marco de agregación. Necesitas $group sus documentos por "usuario" y devolver el último documento para cada usuario usando el $last operador acumulador, pero para que esto funcione, necesita una etapa de clasificación preliminar usando el $sort operador de tubería de agregación. Para ordenar sus documentos, debe considerar tanto el campo "creado en" como el campo "usuario".

La última etapa en la canalización es el $match etapa en la que selecciona solo los últimos documentos donde "isAbandoned" es igual a true .

db.students.aggregate([
    { "$sort": { "user": 1, "createdAt": 1 } }, 
    { "$group": { 
        "_id": "$user", 
        "last": { "$last": "$$ROOT" }
    }}, 
    { "$match": { "last.isAbandoned": true } }
])

que devuelve algo como esto:

{ 
    "_id" : ObjectId("56c85244bd5f92cd78ae4bc1"),
    "last" : {
        "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
        "user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
        "studentName" : "Rajeev",
        "createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
        "isAbandoned" : true
    }
}

Para obtener el resultado esperado, necesitamos usar $replaceRoot operador de tubería a partir de la versión 3.4 para promover el documento incrustado al nivel superior

{
    $replaceRoot: { newRoot: "$last" }
}

En una versión anterior, debe usar el $project operación de tubería de agregación para remodelar nuestros documentos. Entonces, si extendemos nuestra canalización con la siguiente etapa:

{ 
    "$project": { 
        "_id": "$last._id", 
        "user": "$last.user", 
        "studentName": "$last.studentName", 
        "createdAt": "$last.createdAt", 
        "isAbandoned": "$last.isAbandoned"
}}

produce el resultado esperado:

{
    "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
    "user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
    "studentName" : "Rajeev",
    "createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
    "isAbandoned" : true
}