2016-09-20 45 views
2

我有一個包含一個字符串數組的列的數據庫。實施例表:如何通過在MongoDB中將數組元素與MapReduce進行匹配來對文檔進行分組?

name | words       | ... 
Ash | ["Apple", "Pear", "Plum"]  | ... 
Joe | ["Walnut", "Peanut"]   | ... 
Max | ["Pineapple", "Apple", "Plum"] | ... 

現在我想該錶針對通過匹配率的單詞和組的文檔的給定陣列相匹配。

示例輸入與預期的結果:

// matched for input = ["Walnut", "Peanut", "Apple"] 
{ 
    "1.00": [{name:"Joe", match:"1.00"}], 
    "0.33": [{name:"Ash", match:"0.33"}, {name:"Max", match:"0.33"}] 
} 

我使用以下map功能與匹配率作爲關鍵排放文檔:

function map() { 
    var matches = 0.0; 
    for(var i in input) 
     if(this.words.indexOf(input[i]) !== -1) matches+=1; 
    matches /= input.length; 
    var key = ""+matches.toFixed(2); 
    emit(key, {name: this.name, match: key}); 
} 

現在缺少的是一個匹配reduce函數來將發射的KV對組合成結果對象。

我已經嘗試過這樣的:

function reduce(key, value) { 
    var res = {}; 
    res[key] = values; 
    return res; 
} 

但是我對此

MongoDB中可以調用函數減少多次爲同一 關鍵規範的麻煩。在這種情況下, 該鍵的reduce函數的前一個輸出將成爲該鍵的下一個減少函數調用的輸入值之一。

...產生嵌套的結果對象。根據他們的比賽將文檔分組的正確方法是什麼?

回答

1

爲同一個鍵多次調用reduce函數。

這就是idempotence,並且reduce函數必須尊重它。

但是,爲了簡單起見,您只需確保地圖輸出格式與縮小格式相同。

對於你的情況,這樣的事情會工作:

db.col.insert({"name": "Ash", "words": ["Apple", "Pear", "Plum"]}) 
db.col.insert({"name": "Joe", "words": ["Walnut", "Peanut"]}) 
db.col.insert({"name": "Max", "words": ["Pineapple", "Apple", "Plum"]}) 

function map() { 

    input = ["Walnut", "Peanut", "Apple"] 

    var matches = 0.0; 
    for(var i in input) 
     if(this.words.indexOf(input[i]) !== -1) matches+=1; 
    matches /= input.length; 
    var key = ""+matches.toFixed(2); 

    emit(key, {users: [{name: this.name, match: key}]}); 
} 

function reduce(key, value) { 

    ret = value[0] 

    for(var i=1; i<value.length; i++){ 
     ret.users = ret.users.concat(value[i].users) 
    } 

    return ret 

} 

db.col.mapReduce(map, reduce, {"out": {inline:1}}) 

輸出:

{ 
    "results" : [ 
     { 
      "_id" : "0.33", 
      "value" : { 
       "users" : [ 
        { 
         "name" : "Ash", 
         "match" : "0.33" 
        }, 
        { 
         "name" : "Max", 
         "match" : "0.33" 
        } 
       ] 
      } 
     }, 
     { 
      "_id" : "0.67", 
      "value" : { 
       "users" : [ 
        { 
         "name" : "Joe", 
         "match" : "0.67" 
        } 
       ] 
      } 
     } 
    ], 
    "timeMillis" : 22, 
    "counts" : { 
     "input" : 3, 
     "emit" : 3, 
     "reduce" : 1, 
     "output" : 2 
    }, 
    "ok" : 1 
} 
+1

謝謝,這正是我之後。非常有用的答案! – Appleshell

相關問題