mongoDB-MapReduce finalize创建NaN值

mongoDB-MapReduce finalize创建NaN值,mongodb,mapreduce,mongodb-query,aggregation-framework,Mongodb,Mapreduce,Mongodb Query,Aggregation Framework,我为以下数据结构创建了MapReduce作业: { "_id" : 1), "docid" : 119428, "term" : 5068, "score" : 0.198 } { "_id" : 2), "docid" : 154690, "term" : 5068, "score" : 0.21 } { "_id" : 3), "docid" : 156278, "term" : 5068, "score" : 0.128 } { "_id" : 4), "docid" : 700, "t

我为以下数据结构创建了MapReduce作业:

{ "_id" : 1), "docid" : 119428, "term" : 5068, "score" : 0.198 }
{ "_id" : 2), "docid" : 154690, "term" : 5068, "score" : 0.21 }
{ "_id" : 3), "docid" : 156278, "term" : 5068, "score" : 0.128 }

{ "_id" : 4), "docid" : 700, "term" : "fire", "score" : 0.058 }
{ "_id" : 5), "docid" : 857, "term" : "fire", "score" : 0.133 }
{ "_id" : 6), "docid" : 900, "term" : "fire", "score" : 0.191 }
{ "_id" : 7), "docid" : 902, "term" : "fire", "score" : 0.047 }
    { "_id" : "fire", "value" : { "cnt" : 333, "scoresum" : "[object 
BSON][object BSON]0.176[object BSON]0.1010.181[object BSON][object .....BSON]
[object BSON][object BSON]0.1910.1710.2010.363[object BSON][object BSON]", "avg" : NaN } }
我想按学期分组,然后计算平均分数

这是我的MapReduce函数:

db.keywords.mapReduce( 
  function(){ 
      emit( this.term, this.score ); 
  }, 
  function(key, values) { 
      rv = { cnt : 0, scoresum : 0}; 
      rv.cnt = values.length; rv.scoresum = Array.sum(values); 
      return rv; 
  },  
  { 
     out: "mr_test" , 
     finalize: function(key, reduceVal) { 
        reduceVal.avg = reduceVal.scoresum / reduceVal.cnt; 
        return reduceVal;  
     } 
   } 
)
有些计算值是正确的:

{ "_id" : 5068, "value" : { "cnt" : 5, "scoresum" : 0.887, "avg" : 0.1774 } }
但其他人正在创造一些奇怪的结构:

{ "_id" : 1), "docid" : 119428, "term" : 5068, "score" : 0.198 }
{ "_id" : 2), "docid" : 154690, "term" : 5068, "score" : 0.21 }
{ "_id" : 3), "docid" : 156278, "term" : 5068, "score" : 0.128 }

{ "_id" : 4), "docid" : 700, "term" : "fire", "score" : 0.058 }
{ "_id" : 5), "docid" : 857, "term" : "fire", "score" : 0.133 }
{ "_id" : 6), "docid" : 900, "term" : "fire", "score" : 0.191 }
{ "_id" : 7), "docid" : 902, "term" : "fire", "score" : 0.047 }
    { "_id" : "fire", "value" : { "cnt" : 333, "scoresum" : "[object 
BSON][object BSON]0.176[object BSON]0.1010.181[object BSON][object .....BSON]
[object BSON][object BSON]0.1910.1710.2010.363[object BSON][object BSON]", "avg" : NaN } }

我的MapReduce函数有什么问题?

您错过了处理以下MapReduce操作的基本规则:

MongoDB可以为同一个键多次调用reduce函数。在这种情况下,该键的reduce函数的上一个输出将成为该键的下一个reduce函数调用的输入值之一

这意味着“两个”映射器和减速器函数<强>必须< /强>发出完全相同的结构,并考虑该结构用于输入。当然,问题是,如果您在reduce函数中输出不同的结构,那么下次它返回reduce时,输入的结构就不是预期的结构

这就是mapReduce处理同一个键的大数据的方式,通过一次又一次地逐步减少,直到给定键只有一个结果:

db.keywords.mapReduce(
函数(){
emit(this.term,{“cnt”:1,“score”:this.score});
}, 
函数(键、值){
rv={“cnt”:0,“score”:0};
values.forEach(函数(值){
rv.cnt+=value.cnt;
rv.score+=value.score;
});
返回rv;
},  
{ 
“out”:“mr_测试”,
“finalize”:函数(键,reduceVal){
reduceVal.avg=reduceVal.score/reduceVal.cnt;
返回还原值;
} 
}
)
但实际上,通过这种方法,整个过程的效率要高得多:

db.keywords.aggregate([
{“$组”:{
“_id”:“$term”,
“cnt”:{“$sum”:1},
“分数”:{“$sum”:“$score”},
“平均值”:{“$avg”:“$score”}
}},
{“$out”:“aggtest”}
])
它甚至还有一个聚合累加器,可以在一次传递中获得平均值

与mapReduce不同,此处使用的运算符在本机代码中执行,而不是在解释的JavaScript中执行。结果更快,通过数据的次数更少


事实上,只有一个传递,它只是集合的可选输出,而不是返回默认的游标。光标是相对于mapReduce的另一个优势。

您错过了处理mapReduce操作的基本规则:

MongoDB可以为同一个键多次调用reduce函数。在这种情况下,该键的reduce函数的上一个输出将成为该键的下一个reduce函数调用的输入值之一

这意味着“两个”映射器和减速器函数<强>必须< /强>发出完全相同的结构,并考虑该结构用于输入。当然,问题是,如果您在reduce函数中输出不同的结构,那么下次它返回reduce时,输入的结构就不是预期的结构

这就是mapReduce处理同一个键的大数据的方式,通过一次又一次地逐步减少,直到给定键只有一个结果:

db.keywords.mapReduce(
函数(){
emit(this.term,{“cnt”:1,“score”:this.score});
}, 
函数(键、值){
rv={“cnt”:0,“score”:0};
values.forEach(函数(值){
rv.cnt+=value.cnt;
rv.score+=value.score;
});
返回rv;
},  
{ 
“out”:“mr_测试”,
“finalize”:函数(键,reduceVal){
reduceVal.avg=reduceVal.score/reduceVal.cnt;
返回还原值;
} 
}
)
但实际上,通过这种方法,整个过程的效率要高得多:

db.keywords.aggregate([
{“$组”:{
“_id”:“$term”,
“cnt”:{“$sum”:1},
“分数”:{“$sum”:“$score”},
“平均值”:{“$avg”:“$score”}
}},
{“$out”:“aggtest”}
])
它甚至还有一个聚合累加器,可以在一次传递中获得平均值

与mapReduce不同,此处使用的运算符在本机代码中执行,而不是在解释的JavaScript中执行。结果更快,通过数据的次数更少

事实上,只有一个传递,它只是集合的可选输出,而不是返回默认的游标。光标是相对于mapReduce的另一个优势