MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Sammlungsdaten nach mehreren Feldern gruppieren mongodb

Mit dem Aggregations-Framework weicht das Ergebnis geringfügig von Ihrer "gewünschten" Ausgabe ab, da Sie anstelle von Hash-Schlüsseln ein Array von Objekten mit der _id erhalten Schlüssel mit einem Wert, der Ihre Gruppierung nach Feld darstellt. Zum Beispiel statt

{
    "28-10-2016":{
        "success_count": 10, 
        "failure_count": 10
    },
    "29-10-2016": {
        "success_count": 10, 
        "failure_count": 10
    }
}

Sie hätten eine bessere Struktur wie

[
    {
        "_id": "28-10-2016",
        "success_count": 10, 
        "failure_count": 10
    },
        "_id": "29-10-2016",
        "success_count": 10, 
        "failure_count": 10
    }
]

Um das obige Ergebnis zu erzielen, wäre die Verwendung von $cond Operator im $sum Akkumulator-Operator. Der $cond -Operator wertet eine logische Bedingung basierend auf ihrem ersten Argument (wenn) aus und gibt dann das zweite Argument zurück, wenn die Auswertung wahr ist (dann), oder das dritte Argument, wenn falsch (sonst). Dadurch wird die Wahr/Falsch-Logik in numerische Werte von 1 und 0 umgewandelt, die in $sum bzw.:

"success_count": {
    "$sum": {
        "$cond": [ { "$eq": [ "$status", "success" ] }, 1, 0 ]
    }
}

Als resultierende Pipeline muss man die Aggregationsoperation ausführen, die den $dateToString Operator in der _id Schlüsselausdruck für den $gruppe Leitung:

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);
})

Es gibt jedoch einen flexibleren und leistungsfähigeren Ansatz, der viel schneller ausgeführt wird als der oben genannte, bei dem die effizienteste Datenstruktur für Ihr Aggregationsergebnis beispielsweise dem Schema folgt:

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 }
        ]
    }
]

Erwägen Sie dann, eine alternative Pipeline wie folgt auszuführen

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);
})