2011-11-25 56 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; 
} 

在最終化函數只計算平均。