標籤:
建立下述測試資料,通過MapReduce統計每個班級學生數及成績和。
代碼如下:
public string SumStudentScore(){ var collection = _dataBase.GetCollection("StudentInfo"); //按照班級(Class)進行分組統計,並將每條記錄的記錄數(1)和成績(this.Score)作為Reduce參數 string mapFunction = @"function(){ emit(this.Class,{Count:1,Score:this.Score}); };"; //注意此處Values是分組後的一到多條記錄 string reduceFunction = @"function(Class,Values){ var reduced = {SumCount:0,SumScore:0}; Values.forEach(function(val){ reduced.SumCount += val.Count; reduced.SumScore += val.Score; }); return reduced; }"; string outputInfo = string.Empty; var result = collection.MapReduce(mapFunction, reduceFunction); foreach (var item in result.GetResults()) { outputInfo += item.ToString() + Environment.NewLine; } return outputInfo;}
執行結果如下:
{ "_id" : "11班", "value" : { "SumCount" : 2.0, "SumScore" : 9.0 } }
{ "_id" : "12班", "value" : { "SumCount" : 2.0, "SumScore" : 8.0 } }
{ "_id" : "13班", "value" : { "Count" : 1.0, "Score" : 5.0 } }
可見統計結果沒有問題,但是第三個分組13班的返回格式明顯不同於前兩條,經查閱資料為誤用MapReduce所致,MapReduce使用有如下要求:
Reduce方法的Value參數必須與返回結果一致。
再分析上述代碼:
Reduce的Values參數是由Map方法emit而來,因此參數格式為:{Count:Number,Score:Number},而Reduce的返回參數格式為:{SumCount:Number,SumScore:Number},格式並不一致,因此導致了上述問題。
修改上述代碼,將emit結果與Reduce返回格式保持一致:
public string SumStudentScore(){ var collection = _dataBase.GetCollection("StudentInfo"); //按照班級(Class)進行分組統計,並將每條記錄的記錄數(1)和成績(this.Score)作為Reduce參數 string mapFunction = @"function(){ emit(this.Class,{SumCount:1,SumScore:this.Score}); };"; //注意此處Values是分組後的一到多條記錄 string reduceFunction = @"function(Class,Values){ var reduced = {SumCount:0,SumScore:0}; Values.forEach(function(val){ reduced.SumCount += val.SumCount; reduced.SumScore += val.SumScore; }); return reduced; }"; string outputInfo = string.Empty; var result = collection.MapReduce(mapFunction, reduceFunction); foreach (var item in result.GetResults()) { outputInfo += item.ToString() + Environment.NewLine; } return outputInfo;}
輸出結果正確:
{ "_id" : "11班", "value" : { "SumCount" : 2.0, "SumScore" : 9.0 } }
{ "_id" : "12班", "value" : { "SumCount" : 2.0, "SumScore" : 8.0 } }
{ "_id" : "13班", "value" : { "SumCount" : 1.0, "SumScore" : 5.0 } }
參考資料:
關於《來,我給你們看一段神奇的mongodb的mapreduce操作!》的解釋
db.collection.mapReduce() — MongoDB Manual 2.6.7
MongoDB中通過MapReduce實現合計Sum功能及返回格式不一致問題分析