简体   繁体   中英

Is it possible to iterate over mapReduce in MongoDB

I am using mapReduce in MongoDB to generate the trending songs for a user form his/her friends network. so I iterate over all users and check if the user_id exists in their friends array, if it exists I emit their songs and then merge the whole emitted songs to find the top songs for all his friends network.

The problem is that i need to iterate over all users to find the (network trending songs) for every user in the collection. How can I accomplish this, Is there way like nested mapReduce. or do I have to iterate from the application layer, like excuting mapReduce through a for loop!.

my current mapReduce that i am using is this one:

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})

You could certainly use a for-loop in your application to cycle over the user IDs and run your map reduce for each one. However, for something like this, you might have better luck using the aggregation framework to create a pipeline of aggregate operations to do it all at once.

I don't know the precise details of your schema, but I think you could build an aggregation pipeline along the lines of this:

  • $unwind to get a flat list of users mapped to their friends' user IDs
  • $unwind again to map the friends' user IDs to their list of songs
  • $group to get the aggregates of each song in the resulting list
  • $sort to put the resulting stuff in order

In reality your pipeline might require a few more steps, but I think that if you look at this problem in terms of aggregation rather than map-reduce, it will be easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM