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

agrupar dados de coleta por vários campos mongodb


Com a estrutura de agregação, o resultado será um pouco diferente da sua saída "desejada", pois em vez de ter chaves de hash, você obtém uma matriz de objetos com o _id chave com um valor que representa seu grupo por campo. Por exemplo, em vez de
{
    "28-10-2016":{
        "success_count": 10, 
        "failure_count": 10
    },
    "29-10-2016": {
        "success_count": 10, 
        "failure_count": 10
    }
}

você teria uma estrutura melhor como
[
    {
        "_id": "28-10-2016",
        "success_count": 10, 
        "failure_count": 10
    },
        "_id": "29-10-2016",
        "success_count": 10, 
        "failure_count": 10
    }
]

A obtenção do resultado acima exigiria o uso do $cond operador no $sum operador de acumulador. O $cond O operador avaliará uma condição lógica com base em seu primeiro argumento (if) e, em seguida, retornará o segundo argumento onde a avaliação for verdadeira (então) ou o terceiro argumento onde for falso (else). Isso converte a lógica verdadeira/falsa em valores numéricos 1 e 0 que alimentam $sum respectivamente:
"success_count": {
    "$sum": {
        "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
    }
}

Como um pipeline resultante, é necessário executar a operação de agregação que usa o $dateToString operador no _id expressão-chave para o $grupo encanamento:
Orders.aggregate([
    {
        "$group": {
            "_id": {
                "$dateToString": { 
                    "format": "%Y-%m-%d", 
                    "date": "$created_at" 
                }
            },
            "success_count": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
                }
            },
            "failure_count": {
                "$sum": {
                    "$cond": [ { "$eq": [ "$status", "failure" ] }, 1, 0 ]
                }
            }
        }
    }
], function (err, orders){
    if (err) throw err;
    console.log(orders);
})

No entanto, existe uma abordagem mais flexível e de melhor desempenho que executa muito mais rápido do que a acima, onde a estrutura de dados mais eficiente para o resultado da agregação segue o esquema, por exemplo:
orders = [
    {
        "_id": "28-10-2016",
        "counts": [
            { "status": "success", "count": 10 },
            { "status": "failure", "count": 10 }
        ]
    },
    {
        "_id": "29-10-2016",
        "counts": [
            { "status": "success", "count": 10 },
            { "status": "failure", "count": 10 }
        ]
    }
]

Em seguida, considere executar um pipeline alternativo da seguinte maneira
Orders.aggregate([
    { 
        "$group": {
            "_id": { 
                "date":  {
                    "$dateToString": { 
                        "format": "%Y-%m-%d", 
                        "date": "$created_at" 
                    }
                },
                "status": { "$toLower": "$status" }
            },
            "count": { "$sum": 1 }
        }
    },
    { 
        "$group": {
            "_id": "$_id.date",
            "counts": {
                "$push": {
                    "status": "$_id.status",
                    "count": "$count"
                }
            }
        }
    }
], function (err, orders){
    if (err) throw err;
    console.log(orders);
})