I have a MongoDB collection (named "catalog") containing about 5 astronomical catalogs. Several of these catalogs reference each other, so one of the the documents might look something like this:
{ "_id" : ObjectId("4ec574a68e4e7a519166015f"), "bii" : 20.9519, "class" : 2480, "cpdname" : "CPD -21 6109", "decdeg" : -21.8417, "decpm" : 0.004, "dmname" : "-21 4299", "hdname" : "HD 145612", "lii" : 352.8556, "name" : "PPM 265262", "ppmname" : "PPM 265262", "radeg" : 243.2005, "rapm" : 0.0012, "vmag" : 9.6, "xref" : [ ] }
What I want to do is use mapreduce to move the fields such as "hdname","ppmname", etc into the xref array (then unset them).
So I try to do this one at a time, starting with the hdname field. Here are the map and reduce functions:
map = function() {
for (var hdname in this.hdname) {
emit(this._id,this.hdname);
}
}
reduce = function(key, values) {
var result = [];
for (var hdname in values) {
result.push(hdname);
}
return result;
}
I try running the following command in the mongo shell:
db.catalog.mapReduce(map, reduce,"catalog2");
Unfortunately, I get the following error:
Thu Nov 17 15:52:17 uncaught exception: map reduce failed:{
"assertion" : "reduce -> multiple not supported yet",
"assertionCode" : 10075,
"errmsg" : "db assertion failure",
"ok" : 0
}
Obviously I'm a newbie... can anyone help?
Jason
The documentation says "Currently, the return value from a reduce function cannot be an array (it's typically an object or a number)."
So create an object instead and wrap your array in that. Make sure also that the output of reduce is the same as the input type, so you'll need to emit a similar value in the map operation.
BUT ... why use Map-Reduce to do this? If you emit the _id value there's nothing to reduce as each key will be unique. Why not just iterate over the collection copying the values and updating each record one by one?
I recently needed to return a dictionary as well in my reduce step. Solved this by doing
return values.toString();
in my reducer code. After that I have to parse the result to get individuals, but that wasn't a big deal...
try to return object in reduce function
reduce = function(key, values) {
var result = [];
for (var hdname in values) {
result.push(hdname);
}
return {value:result};
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With