1

我試圖使用map-reduce來了解何時可以提供幫助。mongodb - 無法理解爲什麼/如何使用map-reduce

所以我有一個集合命名爲「行動」與100K文檔這樣的:

{ 
    "profile_id":1111, 
    "action_id":2222 
} 

現在我想要做的map-reduce例子。我試圖獲得一份列表「所有用戶和每個人都有的全部操作」。這可能嗎?我的代碼:

db.fbooklikes.mapReduce(
    function(){ 
     emit(this.profile_id, this.action_id); 
    }, 
    function(keyProfile, valueAction){ 
     return Array.sum(valueAction); 
    }, 
    { 
     out:"example" 
    } 
) 

..這是行不通的。結果是:

"counts" : { 
    "input" : 100000, 
    "emit" : 100000, 
    "reduce" : 1146, 
    "output" : 13 
}, 
"ok" : 1, 
"_o" : { 
    "result" : "map_reduce_example", 
    "timeMillis" : 2539, 
    "counts" : { 
     "input" : 100000, 
     "emit" : 100000, 
     "reduce" : 1146, 
     "output" : 13 
    }, 
    "ok" : 1 
}, 

我想要做的事情是可能與map-reduce?

回答

3

嗯,你可以使用它,但更精確的反應是,有可能更好的工具來做你想做的。

MapReduce對於某些任務很方便,但通常在其他情況下不適用時最適合。的MapReduce MongoDB中的預納入日期引進aggregation framework的,通常是你應該用什麼的時候,你可以:

db.fbooklikes.aggregate([ 
    { "$group": { 
     "_id": "$profile_id", 
     "count": { "$sum": 1 } 
    }} 
]) 

這將直接返回計數集合中的每個分組的所有文件「profile_id」的值。

MapReduce需要JavaScript評估,因此運行速度比聚合框架實現的本地代碼功能慢得多。有時候,你不得不使用它,但在簡單的情況下,最好不要,還有一些你需要了解的怪癖:

db.fbooklikes.mapReduce(
    function(){ 
     emit(this.profile_id, 1); 
    }, 
    function(key,values){ 
     return Array.sum(values); 
    }, 
    { 
     out: { "inline": 1 } 
    } 
) 

最重要的事情的人的MapReduce錯過的是,減速幾乎是從來沒有撥打每發射一次鑰匙。實際上,它將以「塊」處理輸出,從而「減少」該輸出的一部分,並將其放回到相對於其他輸出的「減少」,直到該鍵只有一個值。

由於這個原因,從「地圖」函數發出的reduce函數發出的數據類型非常重要。這是一個棘手的問題,如果你不理解函數的那部分內容,會導致怪異的結果。實際上,mapReduce可以處理單個鍵值的大值結果並減少它們的基本方式。

但是一般來說,您應該儘可能使用聚合框架,並且在問題需要某些特殊計算的情況下,或者在需要使用JavaScript進行檢查時需要進行一些複雜的文檔遍歷,那麼是你使用mapReduce的地方。

+0

+1 - 聚合框架更適合這個 – 2014-09-23 01:33:36

+0

謝謝!聚合效果很好!所以,我試圖學習map-reduce,你能提供一些例子在這個集合中使用它嗎? – user3175226 2014-09-23 01:37:59

+1

@ user3175226上面的列表與您所問的內容完全相同。爲了更好地理解使用mapReduce的情況,最好查看[核心文檔](http://docs.mongodb.org/manual/reference/method/db.collection.aggregate/),其中詳細解釋了這些部分,並附帶了示例。另外還有[樣本]部分(http://docs.mongodb.org/manual/tutorial/map-reduce-examples/) – 2014-09-23 01:41:47

2

你不想總結行動id,你想要數它們。所以你想要類似以下的東西

var map = function() { 
    emit(this.profile_id, { action_ids : [this.action_id], count : 1 }); 
} 

var reduce = function(profile_id, values) { 
    var value = { action_ids: [], count: 0 }; 

    for (var i = 0; i < values.length; i++) { 
     value.count += values[i].count; 
     value.action_ids.push.apply(value.action_ids, values[i].action_ids); 
    } 

    return value; 
} 

db.fbooklikes.mapReduce(map, reduce, { out:"example" }); 

這將給你一個行動ID和每個配置文件ID計數數組。可以通過訪問action_ids陣列的length獲得計數,但我認爲我會保持分開以使示例更清晰。

相關問題