2011-09-27 108 views
3

在MongoDB中,我有如下的映射函數:mongodb的地圖減少value.count

var map = function() { 
    emit(this.username, {count: 1, otherdata:otherdata}); 
} 

並如下降低功能:

var reduce = function(key, values) { 
    values.forEach(function(value){ 
     total += value.count; //note this line 
    } 
    return {count: total, otherdata: values[0].otherdata}; //please ignore otherdata 
} 

問題是與行指出:

total += value.count; 

在我的數據集中,reduce函數被調用9次,並且假定映射減少的結果數應該是8908.

通過上面的線,返回的結果會被正確地返回爲8908.

但是,如果我改變了線路:

total += 1; 

返回的結果將只有909,約1/9的假設結果。

而且,我試圖打印(value.count)和打印的結果是1

如何解釋這種現象?

+0

你不需要在某處聲明'total'嗎? – Thilo

回答

7

簡短回答:value.count並不總是等於1。

長答案:這是map reduce的預期行爲:reduce函數會聚合map函數的結果。但是,它會聚合地圖功能的結果,產生中間結果(在本例中爲小計)。然後再減少函數在這些中間結果上運行,因爲它們是map函數的直接結果。等到每個鍵只剩下一箇中間結果時,這就是最終結果。

它可以被看作是中間結果金字塔:

 
emit(...)-| 
      |- reduce -> | 
emit(...)-|   | 
      |   |- reduce ->| 
emit(...)-|   |   | 
      |   |   | 
emit(...)-|- reduce -> |   | 
      |      |-> reduce = final result 
emit(...)-|      | 
            | 
emit(...)--- reduce ------------ >| 
            | 
emit(...)-----------------reduce ->| 

的數量減少和它們的輸入是無法預測的,其目的是保持隱藏。 這就是爲什麼你必須給一個reduce函數返回與輸入相同類型(相同模式)的數據。

2

reduce函數不僅在原始輸入數據上調用,而且在它自己的輸出上調用,直到出現最終結果。所以它需要能夠處理這些中間結果,例如來自早期階段的[{count:5},{count:3},{count:4}]。