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

Retorna o último valor verdadeiro para cada grupo


A melhor maneira de fazer isso é usando a estrutura de agregação. Você precisa $group seus documentos por "usuário" e retorne o último documento para cada usuário usando o $last operador acumulador, mas para que isso funcione, você precisa de um estágio de classificação preliminar usando o $sort operador de pipeline de agregação. Para classificar seus documentos, você precisa considerar tanto o campo "createdAt" quanto o campo "user".

O último estágio no pipeline é o $match estágio em que você seleciona apenas os últimos documentos em que "isAbandonado" é igual a true .
db.students.aggregate([
    { "$sort": { "user": 1, "createdAt": 1 } }, 
    { "$group": { 
        "_id": "$user", 
        "last": { "$last": "$$ROOT" }
    }}, 
    { "$match": { "last.isAbandoned": true } }
])

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

Para obter o resultado esperado, precisamos usar o $replaceRoot operador de pipeline a partir da versão 3.4 para promover o documento incorporado ao nível superior
{
    $replaceRoot: { newRoot: "$last" }
}

Na versão mais antiga, você precisa usar o $project operação de pipeline de agregação para reformular nossos documentos. Então, se estendermos nosso pipeline com o seguinte estágio:
{ 
    "$project": { 
        "_id": "$last._id", 
        "user": "$last.user", 
        "studentName": "$last.studentName", 
        "createdAt": "$last.createdAt", 
        "isAbandoned": "$last.isAbandoned"
}}

ele produz a saída esperada:
{
    "_id" : ObjectId("56cee51503b7cb7b0eda9c4c"),
    "user" : ObjectId("56c85244bd5f92cd78ae4bc1"),
    "studentName" : "Rajeev",
    "createdAt" : ISODate("2016-02-25T11:27:17.281Z"),
    "isAbandoned" : true
}