GeorgieF
GeorgieF

Reputation: 2727

How to map/reduce two MongoDB collections

I am new to map / reduce and trying to figure out a way to collect the following data using map / reduce instead doing it my my (slow) application logic:

I have a collection 'projects' with a 1:n relation to a collection 'tasks'. Now I'd like to receive an array of results that gives me the project names where the first is the project with the most tasks, and the last the project with the least tasks.

Or even better an array of hashes that also tells me how many tasks every project has (assuming the project name is unique:

[project_1: 23, project_2: 42, project_3: 82]

For map I tried something like:

map = function () {
  emit(this.project_id, { count:1 });
}

and reduce:

reduce = function (key, values) {
  var sum = 0;
  values.forEach(function(doc){ sum += 1; });
  return { count:sum };
}

I fired this against my tasks collection:

var mr = db.tasks.mapReduce(map, reduce, { out: "results" });

But I get crucial results when querying:

db[mr.result].find();

I am using Mongoid on Rails and am completely lost with it. Can someone point me into the right direction?

Thx in advance. Felix

Upvotes: 0

Views: 610

Answers (1)

dampier
dampier

Reputation: 5126

Looks generally right, but I spot at least one problem: The summation step in the reduce function should be

  values.forEach(function(doc){ sum += doc.count ; });

because the function may be reducing values that are themselves the product of a prior reduction step, and that therefore have count values > 1.

That's a common oversight, mentioned here: http://www.mongodb.org/display/DOCS/Troubleshooting+MapReduce

Hope that helps!

Upvotes: 2

Related Questions