我正在尝试汇总本文档中的数据包总数。
{
"_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 :(得分: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,
}
如果可能的话,你应该将值作为数值类型的数组发出,因为这会为你提供更多的选项(即聚合)和(除非数据集很大)可能会带来性能上的好处。
答案 1 :(得分: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}});