mongoDB-MapReduce finalize创建NaN值
我为以下数据结构创建了MapReduce作业: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
{ "_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的另一个优势