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

Похоже, вы пытаетесь сделать групповой доступ через тип. Если это так, сначала вы должны испускать тип. Оттуда он почти такой же, как ваш код, но я позволил себе немного почистить его.

Опасайтесь, функция уменьшения может вызываться несколько раз на меньших группах. Поэтому, если вы использовали свой код в закрытой среде, вы можете получить дополнительные запятые. См. 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() 

Al тройчатые:

По желанию OP, вот версия, которая возвращает массив для имен вместо разделенных запятыми список строки:

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] => Массив ( [0] => Массив ( [0] => Массив ( [0]) [0] => Массив ( [0] => Массив ( [0] => => Array ( [0] => Array ( –

+0

Ahh ... да. Я не был уверен, каковы ваши намерения, поэтому я догадался, основываясь на вашем коде. Я изменю свой ответ, чтобы включить пример массива. –

Смежные вопросы