2010-06-04 199 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