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
}