高级数据聚合:在MongoDB集合中计数平均值

问题描述

| 我有一些类似的文件
{
\"browser\" : \"firefox\",\"version\" : \"4.0.1\"
}

{
\"browser\" : \"firefox\",\"version\" : \"3.6.2\"
}

{
\"browser\" : \"ie\",\"version\" : \"8.0\"
}
如何计算所有浏览器的平均值,结果将是:
global firefox: 66%
global ie: 33%

precise firefox:
4.0.1: 50%
3.6.3: 50%
棘手的是,我不想在一个数组中提供所有可用的Firefox版本。 MongoDB查询应在集合中找到所有不同的版本,并对所有这些版本进行平均计数。 提前致谢!     

解决方法

        这是一个使用纯数字生成统计信息的解决方案(例如0.5代替50%):
var m = function() {
  emit(\'global\',this.browser);
  emit(\'local\',[this.browser,this.version]);
};

var r = function(key,values) {
  var global={},local={},total=0,i,j,x;
  if (key == \'global\') {
    values.forEach(function(v) {
      global[v] = (global[v]||0) + 1;
      total += 1;
    });
    for (i in global) { global[i] = global[i] / total; }
    return global;
  } else if (key == \'local\') {
    values.forEach(function(v) {
      if (!local[v[0]]) { local[v[0]] = {}; }
      x = local[v[0]];
      x[v[1]] = (x[v[1]]||0) + 1;
    });
    for (i in local) {
      total = 0;
      x = local[i];
      for (j in x) { total += x[j]; }
      for (j in x) { x[j] = x[j] / total; }
    }
    return local;
  };
};

db.browsers.mapReduce(m,r,{out:\'bout\'});
db.bout.find();
// => { \"_id\" : \"global\",\"value\" : { \"firefox\" : 0.6666666666666666,\"ie\" : 0.3333333333333333 } }
// => { \"_id\" : \"local\",\"value\" : { \"firefox\" : { \"4.0.1\" : 0.5,\"3.6.2\" : 0.5 },\"ie\" : { \"8.0\" : 1 } } }