I'm running into some trouble with a very simple mapreduce, I can't figure out what I've done wrong. I'm trying to merge two collections together, and this first, db.Pos looks like this
"chr" : "chr1", "begin" : 39401, "end" : 39442
The other collection, db.Gene has the following format
"chr" : "chr1", "begin" : 39401, "end" : 39442, "gene" : "GENE1"
My code looks like this:
var mapPos = function(){
emit({chr: this.chr, begin:this.begin, end:this.end},{gene:""});
}
var mapGene = function() {
emit({chr: this.chr, begin:this.begin, end:this.end},{gene:this.gene});
}
r = function(key,values){
var result = {gene:""}
values.forEach(function(value){
result.gene = value.gene;
});
return result;
}
res = db.Pos.mapReduce(mapPos, r, {out: {reduce: 'joined'}});
res = db.Gene.mapReduce(mapGene, r, {out: {reduce: 'joined'}});
So what I'd like to see is a collection where entries that are matching by chr, begin, and end are merged and the gene field is filled in from the db.Gene collection.
Instead, I'm getting the "gene" field in my "joined" collection updated to something other than 0 even when there is no matching doc in db.Gene that has a gene field.
What did I do wrong?
After reflexion, i think you should use
mergeand notreducefor yourout.The reason why you don't have the good value :
The problem is when the reduce is applied between the
joinedcollection content and the result of thedb.Gene.mapReduce.The function
reducedon't know which value is the newest, so theresult.genereturned is the lastvalue.geneof thevaluesarray.To distinguish the value that will override the value existing in the collection, you can add a flag.
Hope it's clear :)