2013-05-30 30 views
2

我正在嘗試聚合本文檔中的數據包總數。Mongodb是否可以聚合一個對象?

{ 
    "_id" : ObjectId("51a6cd102769c63e65061bda"), 
    "capture" : "1369885967", 
    "packets" : { 
     "0" : "595", 
     "1" : "596", 
     "2" : "595", 
     "3" : "595", 
     ... 
    } 
} 

我能得到的最接近的是約

db.collection.aggregate({ $match: { capture : "1369885967" } }, {$group: { _id:null, sum: {$sum:"$packets"}}}); 

但是它返回總和0,這顯然是錯誤的。

{ "result" : [ { "_id" : null, "sum" : 0 } ], "ok" : 1 } 

如何獲得所有數據包的總和?

+0

你需要'$ unwind'這個'packets'子文檔,你也需要把這個子文檔改成一個數組 – Sammaye

+0

不可能是一個對象嗎?如果是這種情況,什麼時候使用對象是合適的? – resting

+0

啊,你知道你得到的對象....嗯....否 – Sammaye

回答

3

既然你有一個對象,而不是一個數組中的值,你需要使用MapReduce的。

// Emit the values as integers 

var mapFunction = 
    function() { 
    for (key in this.packets) { 
     emit(null, parseInt(this.packets[key])); 
    } 
    } 

// Reduce to a simple sum 

var reduceFunction = 
    function(key, values) { 
    return Array.sum(values); 
    } 

> db.collection.mapReduce(mapFunction, reduceFunction, {out: {inline:1}}) 
{ 
    "results" : [ 
     { 
      "_id" : null, 
      "value" : 2381 
     } 
    ], 
    "ok" : 1, 
} 

如果可能的話,你應該發出的值作爲數字類型的數組替代,因爲它爲您提供了更多的選擇(即聚集)和(除非該數據集很大)可能的性能優勢。

+0

我正在考慮是否應該改變結構以將數據包存儲爲數組。我確定會將數據包的值更改爲數字。任何關於前者的建議考慮我可能會做各種查詢,例如,找出哪個時間是最高或最低的數據包?基本上是時間和數據包之間的各種關係。 – resting

1

如果您不知道包子文檔中有多少個鍵,並且您似乎還將計數存儲爲字符串(爲什麼?),您將不得不使用mapReduce。

喜歡的東西:

m=function() { 
    for (f in "this.packets") { 
     emit(null, +this.packets[f]); 
}; 
r=function(k, vals) { 
    int sum=0; 
    vals.forEach(function(v) { sum+=v; }); 
    return sum; 
} 

db.collection.mapreduce(m, r, {out:{inline:1}, query:{your query condition here}}); 
+0

嗯,是的,如果數據包是一個數字類型的數組,它就可以工作; '「errmsg」:「異常:$ unwind:字段路徑末尾的值必須是數組」「。 –

+0

等待你的號碼值是否真的存儲爲字符串? –

+0

更新了我的答案,以迎合兩個字符串而不是數字和未知數量的字段。對不起,早些時候誤讀了這個問題。 –

相關問題