I have some different Map/Reduces functions that I use in my project. But one is a lot different than the others since it requires a loop in the map functionality. And for each count in the loop, I send an emit.
What I have is this scenario (in the user collection):
"channels" : [
"Channel 1",
"Channel 2",
],
What I want to do is to count how many users each channel has. So for that I could use db.users.find({channels: "Channel 1"}).count() but unfortunately channels are dynamic which means I don’t know all the possible channel names and it may well change in the future.
So I thought that a Map/Reduce job would sit just perfect. But the problem is that the first Reduce job I wrote calculated wrong. And the other where I used a query for each emit, would come to take forever (more than 3 hours before the ssh session shut down).
So now I’m stuck and I need help, preferably I would want to have a Map/Reduce job since it’s more nice than a bunch of queries which is kind of slow to run in real time.
This is the latest Map and Reduce functions I wrote:
var map = function() {
if(this.channels) {
for(var i = 0, imax = this.channels.length; i<imax; i++) {
emit(this.channels[i], 1);
}
}
}
var reduce = function (key, values) {
var result = 0;
values.forEach(function (value) {
// had this before: result += 1;
result = db.users.find({'channels' : key}).count();
});
return result;
}
I knew that the reduce function was horrific but I just tried the best I could think of. I think my logic may seem wrong but I can’t find a good solution. Now I’m thinking of just doing a bunch of queries on every page load, but it will be slow as hell.
Please help! 🙂
In your scenario the reduce function should look like this:
Let me know if it is still not working and if it does please give an example of input and (incorrect) output.