MongoDB中的分组和计数

时间:2011-11-25 11:27:41

标签: mongodb group-by mapreduce

我正在尝试对mongodb 2.0.1中每个组的元素数量进行分组和计算,但到目前为止还没有成功。

我的数据库架构如下:

{
    "_id" : ObjectId("4ece7544853b4b0941000000"),
    "ResultSet" : {
            "Results" : [
                    {
                            "quality" : 87,
                            "state" : "Franche-Comté"
                    }
            ]
    }
}

我一直在尝试所有类型的方法,遵循不同的教程,但每次都是相同的结果:只有一个空组...我不明白为什么。

我到目前为止所写的最佳查询如下:

db.extract_2000.group( {
            cond: { "ResultSet.Results.quality": {$exists: true} },
            key: {"ResultSet.Results.state": true}, 
            reduce: function(obj, glob) { glob.total++; glob.quality += obj.ResultSet.Results.quality },
            initial: { total: 0, quality: 0 },
            finalize: function(glob) {glob.avgquality = glob.quality / glob.total}
            })

返回(再次):

[
        {
                "ResultSet.Results.state" : null,
                "total" : 2000,
                "quality" : NaN,
                "avgquality" : NaN
        }
]

我做错了什么?

2 个答案:

答案 0 :(得分:2)

这根本不会像书面那样工作。关键问题在于:key: {"ResultSet.Results.state": true}ResultSet.Results是一个数组。当您要求ResultSet.Results.state时,您暗示要在此处执行某种类型的for循环。 group命令根本无法做到这一点。

请尝试以下M / R:

map = function() {
  // Note that we emit once per result
  foreach(var i in ResultSet.Results) {
    key = this.ResultSet.Results[i];
    value = { count: 1, 
      quality: this.ResultSet.Results[i].quality,
      avg_quality: 0
    };

    emit(key, value);
  }
}

reduce = function(key, values) {
  // note that results has same fields as emitted value
  var results = { count: 0, quality: 0, avg_quality: 0 };
  foreach(var i in values){
    results.count += values[i].count;
    results.quality += values[i].quality;
    // ignore avg_quality, we don't use it
  }
  return results;
}

您还必须为平均值写一个finalize

finalize = function(key, value) {
  if (value.count > 0)
    value.avg_quality = value.quality / value.count;

  return value;
}

答案 1 :(得分:0)

地图功能

map = function() {

    for(var i in this.Results) {
        emit(this.Results[i].state, 
            {quality: this.Results[i].quality, total: 1, avgquality: 0}
        );
    }
}

减少功能

reduce = function(key, values) {
    var data = {quality: 0, total: 0, avgquality: 0};

    for(var i=0; i<values.length; i++) {
        data.quality += values[i].quality;
        data.total += values[i].total;
    }
    return data;
}

在finalize函数中只计算平均值