2012-07-01 55 views
0

我正嘗試在MongoDB中使用mapreduce來運行網頁排名。在mongodb中計算網頁排名

我的文檔格式爲:

{ 
     "_id" : "u: 10000", 
     "value" : [ 
       [ 
         "u: 10000", 
         "s: 985272", 
         1 
       ], 
       [ 
         "s: 985272", 
         "u: 10000", 
         1 
       ], 
       [ 
         "u: 10000", 
         "s: 303770", 
         1 
       ], 
       [ 
         "s: 303770", 
         "u: 10000", 
         1 
       ] 
     ] 
} 

現在我認爲第一步是收集的關鍵環節。但是,我有幾個出站鏈接每個文件。 (這些都恰好是雙向的)。

這裏是我的地圖和減少功能:

m = function() { 
    for (var i = 0; i < this.value.length; i++){ 
     var out = {}; 
     out.out = this.value[i][1]; 
     out.weight = this.value[i][2]; 
     emit(this.value[i][0], [out]); 
    } 
} 

r = function(key, values){ 
    var result = { 
     value: [] 
    }; 
    values.forEach(function(val) { 
    result.value.push({out: val.out, weight: val.weight}); 
    }); 
    return result; 
} 

的問題是我不知道發射時產生每個文檔的多個排放。 當我得到這樣的結果:

{ 
     "_id" : "s: 1000082", 
     "value" : [ 
       { 
         "out" : "u: 37317", 
         "weight" : 1 
       } 
     ] 
} 

當我希望每個文檔的多個項目。

任何人有任何想法?幫助將不勝感激!

編輯:

我並不完全滿意,例如how do things like this work?減少結果看起來完全不像發射輸出。

+0

您能否澄清字段值是什麼?什麼是「s」和「u」等? –

+0

它們只是伴隨身份證件的不同類型的文件(網頁)... – toofarsideways

+0

下面的答案是正確的 - 如果您在向發射值添加更多字段時遇到問題,我會建議開始一個新問題。 –

回答

3

問題是您沒有映射數組,但是您的reduce嘗試推送到數組。

如果你想讓每個鍵映射到一個「out」和「weight」對的數組,那麼你需要發出一個包含它的數組,並且在reduce中你需要將數組連接在一起。

記住,the structure of the object returned by the reduce function must be identical to the structure of the map function's emitted value.

這意味着,當你的地圖發出(鍵,值)「值」的結構必須一致,以一個什麼樣的減少函數的返回結果的結構。

如果您改變了地圖功能,這一點,所以這個值是場「價值」,這是文件的陣列,每個有場「走出去」和區域「重量」的文件:

function() { 
    for (var i = 0; i < this.value.length; i++) { 
     key = this.value[i][0]; 
     value = {value:[{out:this.value[i][1], weight:this.value[i][2]}]}; 
     emit(key, value); 
    } 
} 

和您減少功能這一點,它構造的結果具有相同的結構,你在上面發出值(因爲它只是串接它被傳遞在每個鍵):

function (key, values) { 
    result = {value:[]}; 
    for (var i in values) { 
     result.value = values[i].value.concat(result.value); 
    } 
    return result; 
} 

,那麼你將得到你所期待回來。

{ 
    "_id" : "s: 303770", 
    "value" : { 
     "value" : [ 
      { 
       "out" : "u: 10000", 
       "weight" : 1 
      } 
     ] 
    } 
} 
{ 
    "_id" : "s: 985272", 
    "value" : { 
     "value" : [ 
      { 
       "out" : "u: 10000", 
       "weight" : 1 
      } 
     ] 
    } 
} 
{ 
    "_id" : "u: 10000", 
    "value" : { 
     "value" : [ 
      { 
       "out" : "s: 303770", 
       "weight" : 1 
      }, 
      { 
       "out" : "s: 985272", 
       "weight" : 1 
      } 
     ] 
    } 
} 
+0

是否每個文檔都必須經過縮減步驟?我只問,因爲我在第一個「價值」地圖中添加了排名值,但它只出現在一些文檔中。 (key,values){ result = {rank:1.0,value:[]}; for(var i in values){ result.value = values [i] .value.concat(result.value); } 返回結果; }' – toofarsideways

+0

每個文檔都被映射 - 您必須從映射發出您的reduce函數返回的相同格式。 –

+0

等等,那麼這樣的事情是如何工作的? - > http://kylebanker.com/blog/2009/12/mongodb-map-reduce-basics/。減少結果看起來完全不像發射輸出。 – toofarsideways