2010-06-04 160 views
2

我見過的所有MongoDB MapReduce示例都涉及到計數/添加數字。我需要組合字符串,它看起來像MapReduce是該作業的最佳工具。我有這種格式的大型MongoDB集合:Mongodb MapReduce連接字符串?

{name: userone, type: typeone} 
{name: usertwo, type: typetwo} 
{name: userthree, type: typeone} 

每個名稱只有一種類型,但名稱不一定是唯一的。我想用一個集合列出所有的名字爲特定類型的結束了,無論是在一個逗號分隔的列表或數組,像這樣:

{type: typeone, names: userone, usertwo} 
{type: typetwo, names: userthree} 

我試圖用MapReduce的做到這一點。當一個類型只有一個用戶時,我的功能可以正常工作。但是,當有多個用戶時,'未定義'被存儲在名稱字段中。

我不是很擅長Javascript,而且我還在學習MongoDB,所以它可能是一個簡單的數據類型或範圍錯誤。

這是我的地圖和減少功能。他們怎麼了?

map = function() { 
emit(this.user,{type:this.type}); 
} 

reduce = function(key, values) { 
var all=""; 
for(var i in values) { 
all+=values[i]['type']+","; 
} 
return all; 
} 

回答

5

它在我看來像你正在試圖做一個group-by通過類型。如果是這樣,你應該首先發射類型。從那裏,它和你的代碼幾乎一樣,但我冒昧地把它清理了一下。

請注意,reduce函數可能會在較小的組上調用多次。因此,如果您在分片環境中使用代碼,則可能會得到額外的尾隨逗號。有關更多信息,請參閱Reduce Function

地圖

m = function(){ emit(this.type, {names:this.name}); } 

減少

r = function(key, values){ 
    var all = []; 
    values.forEach(function(x){ 
    all.push(x.names) 
    }) 
    return {"names": all.join(", ")}; 
} 

使用

res = db.users.mapReduce(m,r); db[res.result].find() 

鋁半夏:

每個操作的要求,這裏是返回名稱,而不是用英文逗號分隔字符串數組的一個版本:

m = function() { 
    emit(this.type, {names:this.name}); 
} 

r = function (key, values) { 
    var all = []; 
    values.forEach(function (x) {all.push(x.names);}); 
    return {type:key, names:all}; 
} 

f = function (w, r) { 
    r.names = r.names[0]; 
    return r 
} 

res = db.users.mapReduce(m,r, {finalize:f}); db[res.result].find() 

乾杯!

+1

這很好,現在我該如何修改該代碼,以便在數組中使用名稱而不是逗號分隔列表(如果需要,我可以在客戶端上構建逗號分隔列表)? 簡單地回報{「names」:all}; (0)=> Array( [0] => Array( [0] => Array( [0] => Array( [0]))在映射函數中工作,但得到了一堆醜陋的嵌套數組, => Array( [0] => Array( – 2010-06-04 21:14:11

+0

啊......是的,我不確定你的意圖是什麼,所以我根據你的代碼猜到了,我會修改我的答案以包含一個數組示例。 – 2010-06-04 21:17:59