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
merge
and notreduce
for yourout
.The reason why you don't have the good value :
The problem is when the reduce is applied between the
joined
collection content and the result of thedb.Gene.mapReduce
.The function
reduce
don't know which value is the newest, so theresult.gene
returned is the lastvalue.gene
of thevalues
array.To distinguish the value that will override the value existing in the collection, you can add a flag.
Hope it's clear :)