2011-11-25 73 views
3

我试图对mongodb 2.0.1中每个组的元素数量进行分组和计数,但目前为止没有成功。MongoDB中的组和计数

我的DB模式是这样的:

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

我在做什么错?

+0

我不确定你想要实现什么 - 不知何故,你试图将嵌入式文档而不是文档分组?我认为这不会起作用,并且就我所见,每个嵌入式文档都不会遵守'$ exists'条件。你是否尝试过使用一个简单的对象而不是带有一个子对象数组的对象?计数('总数')可以吗? – mnemosyn

+0

总数可以,我在数据库中有2000个文档。我尝试按照ResultSet.Results.state进行分组。 –

+1

那么,你有2000 *文档*,但这意味着你的reduce函数将不得不手动迭代子文档数组,不是吗?表达式'obj.ResultSet.Results.quality'不能在reduce函数中进行求值,我认为:'结果'是一个数组,但是您像使用普通对象一样使用它。我认为这是罪魁祸首。 – mnemosyn

回答

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; 
} 
0

地图功能

map = function() { 

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

reduce函数

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

在最终化函数只计算平均。