2012-07-10 114 views
26

我想用MongoDB的聚合框架在SQL運行哪些看起來有點像:Mongodb聚合框架|對多個值進行分組?

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

的文檔狀態:

您可以在管線中的文件指定一個單場,以前計算的值,或由幾個傳入字段組成的聚合密鑰。

但是目前還不清楚'幾個傳入字段構成的聚合密鑰實際上是什麼?

我的數據集是有點像這樣:

[{ "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"}] 

我的查詢看起來是這樣的:

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 : { 
      ? 
     }} 
); 

我的直覺是通過對第二組,試圖管的結果,我知道你可以做到這一點,但它不會工作,因爲第一組已經過多地減少了數據集並且丟失了所需的詳細程度。

我想要做的是使用組label,responseCodesuccess,並從結果中獲得值的總和。它看起來有點像:

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 

哪裏有五組:

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

回答

37

OK,所以解決的辦法是指定_id值合計鍵。這被記錄爲here爲:

您可以指定管道中的文檔,先前計算的值或由多個傳入字段組成的聚合密鑰中的單個字段。

但它實際上並未定義聚合鍵的格式。閱讀早前的文檔here我看到以前的collection.group方法可能需要多個字段,並且新框架中使用了相同的結構。

因此,爲了在多個字段組可以使用_id : { success:'$success', responseCode:'$responseCode', label:'$label'}

如:

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

什麼是你的$項目的目的是什麼?原始文件是否大得多?如果沒有排序,跳過也沒什麼意義。如果你需要avg_value爲什麼不使用$ avg?如果你想要sum,爲什麼不把它叫做sum_value?此外count_success和count_responseCode將會是相同的,不知道爲什麼你需要這兩個。 – 2012-07-11 03:02:14

+9

注意:從2.2.0-rc1開始,對多個字段分組進行了輕微更改:_id:{success:1,responseCode:1,label:1}將變爲_id:{success:「$ success」,responseCode: 「$ responseCode」,標籤: 「$標籤」}。 https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/1cYch580h0w – Richard 2012-08-23 23:36:05

+1

答案根據@Richard固定。 – 2013-03-10 20:04:43