0

Sammlung StrukturGruppe Sammlungsdaten durch mehrere Felder MongoDB

Order = new Schema 
    index:   { type: Number, unique: true } 
    number:   Date 
    status:   { type: String, enum: ['success', 'failure'] } 
    created_at:  { type: Date, default: Date.now } 
    updated_at:  { type: Date, default: Date.now } 

ich mit einer Abfrage die Hilfe benötigen, die mir ein Array von Objekten liefert Daten als Erfolgszahl und Versagen, die nach dem Datum gruppiert zählen. Ex-

orders = { 
       28-10-2016:{ 
       success_count: 10, 
       failure_count: 10 
       }, 
       29-10-2016: { 
       success_count: 10, 
       failure_count: 10 
       } 
      } 
+0

folgt hier posten, was Sie tun dies auch die OP schreiben Code in Kommentaren weit –

+0

@ClementAmarnath versucht haben, nicht zu fördern, ist es schwer zu lesen. Verwenden Sie stattdessen den Link [Bearbeiten], um die Frage mit den zusätzlichen Informationen zu aktualisieren. – chridam

+0

@chridam Ich wollte, dass er den betreffenden Code posten und nicht in den Kommentaren, möge es ihm in meinem Kommentar nicht richtig vermittelt werden :-) –

Antwort

4

Mit dem Aggregations Rahmen, das Ergebnis etwas anders sein wird von Ihrem „gewünschte“ Ausgabe als anstelle Hash-Schlüssel zu haben, erhalten Sie eine Reihe von Objekten mit dem _id Schlüssel einen Wert hat, der Sie repräsentiert Gruppe für Feld Zum Beispiel, statt

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

würden Sie eine bessere Struktur haben wie

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

das obige Ergebnis zu erreichen, die $cond Bediener in dem Bediener $sum Akkumulators mit erfordern würde. Der Operator $cond bewertet eine logische Bedingung basierend auf seinem ersten Argument (if) und gibt dann das zweite Argument zurück, bei dem die Auswertung wahr ist (then), oder das dritte Argument mit false (else). Dieser wandelt die Wahr/Falsch-Logik in 1 und 0 numerische Werte, die jeweils $sum in Futtermittel:

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

Als resultierender Pipeline, braucht man den Aggregationsvorgang ausgeführt werden, die den $dateToString Operator in den _id verwendet Schlüsselausdruck für die $group Pipeline:

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

Allerdings gibt es eine flexiblere und besser performant Ansatz, der viel schneller als die oben führt, wo die effizienteste Datenstruktur für die Aggregation Ergebnis das Schema zum Beispiel folgenden:

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

betrachten dann eine alternative Pipeline läuft Bitte als

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

Das ist genau was ich wollte. Danke @chridam! –

Verwandte Themen