2012-07-10 10 views
26

Ich möchte mongoDB die Aggregation Framework ausgeführt, was in SQL ein bisschen aussehen würde verwenden:Mongodb Aggregation Framework | Über mehrere Werte gruppieren?

Zustand
SELECT SUM(A), B, C from myTable GROUP BY B, C; 

Die docs:

Sie ein einzelnes Feld aus den Dokumenten in der Pipeline angeben , ein zuvor berechneter Wert oder ein Aggregatschlüssel, der aus mehreren eingehenden Feldern besteht.

Aber es ist unklar, was ein Aggregatschlüssel aus mehreren eingehenden Feldern tatsächlich ist?

Meine Daten-Set ist ein bisschen wie folgt aus:

[{ "timeStamp" : 1341834988666, "label" : "sharon", "responseCode" : "200", "value" : 10, "success" : "true"}, 
{ "timeStamp" : 1341834988676, "label" : "paul", "responseCode" : "200", "value" : 60, "success" : "true"}, 
{ "timeStamp" : 1341834988686, "label" : "paul", "responseCode" : "404", "value" : 15, "success" : "true"}, 
{ "timeStamp" : 1341834988696, "label" : "sharon", "responseCode" : "200", "value" : 35, "success" : "false"}, 
{ "timeStamp" : 1341834988166, "label" : "paul", "responseCode" : "200", "value" : 40, "success" : "true"}, 
{ "timeStamp" : 1341834988266, "label" : "paul", "responseCode" : "404", "value" : 99, "success" : "false"}] 

Meine Frage wie folgt aussieht:

resultsCollection.aggregate(
    { $match : { testid : testid} }, 
    { $skip : alreadyRead }, 
    { $project : { 
      timeStamp : 1 , 
      label : 1, 
      responseCode : 1 , 
      value : 1, 
      success : 1 
     }}, 
    { $group : { 
      _id : "$label", 
      max_timeStamp : { $timeStamp : 1 }, 
      count_responseCode : { $sum : 1 }, 
      avg_value : { $sum : "$value" }, 
      count_success : { $sum : 1 } 
     }}, 
    { $group : { 
      ? 
     }} 
); 

Mein Instinkt die Ergebnisse durch zu einer zweiten Gruppe zu Rohr versuchen war, ich weiß, du kann dies, aber es wird nicht funktionieren, weil die erste Gruppe bereits den Datensatz zu sehr reduziert und die erforderliche Detailgenauigkeit verloren geht.

Was ich tun möchte, ist eine Gruppe mit label, responseCode und success und erhalten Sie die Summe von Wert aus dem Ergebnis. Es sollte ein bisschen wie folgt aussehen:

label | code | success | sum_of_values | count 
sharon | 200 | true |  10  | 1 
sharon | 200 | false |  35  | 1 
paul | 200 | true |  100  | 2 
paul | 404 | true |  15  | 1 
paul | 404 | false |  99  | 1 

Wo gibt es fünf Gruppen:

1. { "timeStamp" : 1341834988666, "label" : "sharon", "responseCode" : "200", "value" : 10, "success" : "true"} 

2. { "timeStamp" : 1341834988696, "label" : "sharon", "responseCode" : "200", "value" : 35, "success" : "false"} 

3. { "timeStamp" : 1341834988676, "label" : "paul", "responseCode" : "200", "value" : 60, "success" : "true"} 
    { "timeStamp" : 1341834988166, "label" : "paul", "responseCode" : "200", "value" : 40, "success" : "true"} 

4. { "timeStamp" : 1341834988686, "label" : "paul", "responseCode" : "404", "value" : 15, "success" : "true"} 

5. { "timeStamp" : 1341834988266, "label" : "paul", "responseCode" : "404", "value" : 99, "success" : "false"} 

Antwort

37

OK, so dass die Lösung ist, eine Sammelschlüssel für den _id Wert angeben. Dies wird dokumentiert here als:

Sie ein einzelnes Feld aus den Dokumenten in der Pipeline angeben können, ein zuvor berechneten Wert oder ein Aggregat Schlüssel aus mehreren eingehenden Feldern aus.

Aber es definiert nicht tatsächlich das Format für einen Aggregatschlüssel. Lesen der früheren Dokumentation here Ich sah, dass die vorherige collection.group-Methode mehrere Felder und die gleiche Struktur im neuen Framework verwendet werden konnte.

resultsCollection.aggregate(
{ $match : { testid : testid} }, 
{ $skip : alreadyRead }, 
{ $project : { 
     timeStamp : 1 , 
     label : 1, 
     responseCode : 1 , 
     value : 1, 
     success : 1 
    }}, 
{ $group : { 
     _id : { success:'$success', responseCode:'$responseCode', label:'$label'}, 
     max_timeStamp : { $timeStamp : 1 }, 
     count_responseCode : { $sum : 1 }, 
     avg_value : { $sum : "$value" }, 
     count_success : { $sum : 1 } 
    }} 
); 
+1

was ist der Zweck Ihrer $ Projekt:

So gruppieren über mehrere Felder könnten Sie _id : { success:'$success', responseCode:'$responseCode', label:'$label'}

Wie benutzen? ist das Originaldokument viel größer? Auch überspringen macht ohne eine Art davor keinen Sinn. und wenn Sie avg_value brauchen, warum nicht $ avg verwenden? Wenn du summierst, warum nennst du es sum_value nicht? Auch count_success und count_responseCode werden gleich sein, nicht sicher, warum Sie beide benötigen. –

+9

Anmerkung: Ab 2.2.0-rc1 wurden geringfügige Änderungen an der Gruppierung durch mehrere Felder vorgenommen: _id: {Erfolg: 1, ResponseCode: 1, Label: 1} würde _id werden: {Erfolg: "$ Erfolg", responseCode: "$ responseCode", Label: "$ label"}. https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/1cYch580h0w – Richard

+1

Antwort behoben gemäß @Richard. –

Verwandte Themen