I’m working on a mapReduce script for MongoDB but I’m stuck with a rather beginnerish JavaScript problem: I can't construct the path to a nested object. The setting is this: in the reduce step I have a nested object containing all possible properties (and some example values).
var result = {
computers: {
total: 12,
servers: {
total: 2,
os: {
unix: 2,
windows: 0
}
},
clients: {
total: 10,
os: {
unix: 3,
windows: 7
}
}
}
}
From the mapping step I get incoming documents like the following:
var incoming = {
computers {
total: 1,
clients: {
total: 1,
os: {
windows: 1
}
}
}
}
The incoming documents are logically subsets of the result document: the ordering of elements and the possible elements are the same, they are just not complete: one may only contain servers data, the other may contain only client data, a third may contain both etc.
I would like to traverse the incoming document and for each property add it’s value to the corresponding property in the result document. Traversing the incoming document recursively is not the problem (I think) but constructing the path is. I came up with the following code:
var traverse = function(knots, path) {
for (var k in knots) {
if (knots[k] !== null && typeof(knots[k]) == "object") {
path = path[knots[k]];
traverse(knots[k], path);
}
else {
// do something to get rid of the root-level incoming object
var rest = incoming.computers;
result[rest][knots[k]] += incoming[rest][knots[k]];
}
}
};
traverse(incoming.computers, incoming.computers);
This script isn’t working. I suspect that the ways I try to concatenate the path (line 4) and pass it to the addition operator (line 7) are both broken.
MongoDB responds with “16722 TypeError: Cannot read property '1' of undefined” but I can't make much sense of that.
Edit: Changed the code above: now calling traverse[path] with an object (following Felix' hint). Follow-up problem is that I don't know how to get rid of the 'incoming' root object when constructing the paths in the else clause. var rest = incoming.computers;
doesn't seem to do the trick. At least MongoDB is still responding with the same error as above.