Можно ли перебирать mapReduce в MongoDB

Я использую mapReduce в MongoDB для создания популярных песен для пользователя из его/ее сети друзей. поэтому я перебираю всех пользователей и проверяю, существует ли user_id в их массиве друзей, если он существует, я испускаю их песни, а затем объединяю все выпущенные песни, чтобы найти лучшие песни для всей его сети друзей.

Проблема в том, что мне нужно перебрать всех пользователей, чтобы найти (популярные в сети песни) для каждого пользователя в коллекции. Как я могу это сделать, есть ли способ, похожий на вложенный mapReduce. или мне нужно выполнить итерацию с прикладного уровня, например, выполнить mapReduce через цикл for!.

мой текущий mapReduce, который я использую, таков:

var map = function() {
users = [];
songs = [];
    if(this.value.friends !== undefined && this.value.friends.length !== 0 && this.value.songs !== undefined && this.value.songs.length !== 0){
        key = this._id.user_id;
        for(var x=0; x<this.value.songs.length; x++)
            emit({user_id:user_id,song_id:this.value.songs[x][0]},{played:this.value.songs[x][1], counter:1});
    }
};
var reduce = function(key, values) {
    var counter = 0;
    var played = 0;
    values.forEach(function(val){
        counter += val.counter;
        played += val.played;
    });
    return {played : played, counter : counter};
};
db.runCommand({"mapreduce":"trending_users", "map":map, "reduce":reduce, "scope":{user_id: "111222333444"} ,"query":{'value.friends':{$in : ['111222333444'] }},'out':{merge:'trending_user_network'}})    
db.trending_user_network.find({'_id.user_id':'111222333444'}).sort({'value.counter':-1, 'value.played':-1})

person Alaa Qutaish    schedule 28.09.2012    source источник


Ответы (1)


Вы, безусловно, можете использовать цикл for в своем приложении, чтобы перебирать идентификаторы пользователей и запускать сокращение карты для каждого из них. Однако для чего-то подобного вам может повезти с помощью среды агрегации для создания конвейер совокупных операций, чтобы сделать все сразу.

Я не знаю точных деталей вашей схемы, но я думаю, что вы могли бы построить конвейер агрегации следующим образом:

  • $unwind чтобы получить плоский список пользователей, сопоставленных с идентификаторами пользователей их друзей
  • $unwind еще раз, чтобы сопоставить идентификаторы пользователей друзей с их списком песен
  • $group чтобы получить совокупность каждой песни в результирующем списке
  • $sort чтобы упорядочить полученный материал

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

person friedo    schedule 28.09.2012
comment
Я ожидаю запустить базу данных в среде сегментов, в этом случае mapReduce будет более эффективным. в то же время, если бы у меня было около 100 тысяч пользователей, то перебор их и вызов mapReduce каждый раз будет действительно ресурсоемкой задачей, а также блокирующей работой. вот что меня смущает. Спасибо. - person Alaa Qutaish; 28.09.2012
comment
Я считаю, что платформа агрегации 2.2 поддерживает сегментированные коллекции, и она намного быстрее, чем MR для запросов по требованию, но главная проблема заключается в том, что она должна делать все в оперативной памяти. Так что для действительно больших коллекций это все еще проблема. Агрегация по-прежнему не быстрая, но 2.2 на голову выше старого JS-движка. С MR вы используете движок JS, и его нельзя использовать по требованию. Это гораздо лучше подходит для вещей, которые вы можете предварительно вычислить и кэшировать, когда менее важно, сколько времени потребуется для сборки. - person cirrus; 30.09.2012
comment
Если вы опубликуете пример данных схемы БД и покажете желаемый результат, мы можем попробовать построить для вас запрос агрегации. - person cirrus; 30.09.2012
comment
Вот пример данных, обратите внимание, что эта коллекция tending_users является результатом промежуточного mapReduce, поэтому я избегаю очень больших и сложных функций mapReduce. paste2.org/p/2288624 желаемый результат - каждый user_id со всеми песнями его/ее друзей сеть. Спасибо! - person Alaa Qutaish; 01.10.2012