MongoDB中通过MapReduce实现合计Sum功能及返回格式不一致问题分析

建立下述测试数据,通过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

时间: 2024-08-04 06:25:12

MongoDB中通过MapReduce实现合计Sum功能及返回格式不一致问题分析的相关文章

如何在Mongodb中实现数据超时自动删除功能?

在工作过程中,我们难免会遇到这样的问题,我们想保存一些数据,但是我们对这些数据的要求并不高,有时候往往只是想要某个时间范围内的数据,比如我们如果永远只关心从当前时间往前推半年内的数据特性,那么我们就不需要将所有数据都保存起来,因为不仅浪费磁盘空间,而且随着数据量的不断累积,其他性能也会受到影响. 这时候我们迫切的需要一直方法能够在我们插入数据的时候自动的帮我们去删除我们过一段时间就不想要的数据,那么怎么实现呢? 在Mongodb内部,有一个特殊的索引,称为TTL索引,通过该索引便可以实现上面的功

MongoDB中的聚合操作

根据MongoDB的文档描述,在MongoDB的聚合操作中,有以下五个聚合命令. 其中,count.distinct和group会提供很基本的功能,至于其他的高级聚合功能(sum.average.max.min),就需要通过mapReduce来实现了. 在MongoDB2.2版本以后,引入了新的聚合框架(聚合管道,aggregation pipeline ,使用aggregate命令),是一种基于管道概念的数据聚合操作. Name Description count Counts the num

Mongodb中数据聚合之聚合管道aggregate

在之前的两篇文章<Mongodb中数据聚合之基本聚合函数count.distinct.group>和<Mongodb中数据聚合之MapReduce>中,我们已经对数据聚合提供了两种实现方式,今天,在这篇文章中,我们讲讲在Mongodb中的另外一种数据聚合实现方式--聚合管道aggregate. 面对着广大用户对数据统计的需求,Mongodb从2.2版本之后便引入了新的功能聚合框架(aggregation framework),它是数据聚合的新框架,这个概念类似于数据处理中的管道.每

在MongoDB中实现聚合函数

在MongoDB中实现聚合函数 随着组织产生的数据爆炸性增长,从GB到TB,从TB到PB,传统的数据库已经无法通过垂直扩展来管理如此之大数据.传统方法存储和处理数据的成本将会随着数据量增长而显著增加.这使得很多组织都在寻找一种经济的解决方案,比如NoSQL数据库,它提供了所需的数据存储和处理能力.扩展性和成本效率.NoSQL数据库不使用SQL作为查询语言.这种数据库有多种不同的类型,比如文档结构存储.键值结构存储.图结构.对象数据库等等. 我们在本文中使用的NoSQL是MongoDB,它是一种开

MongoDB中聚合工具Aggregate等的介绍与使用

Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY.聚合工具可以让开发人员直接使用MongoDB原生的命令操作数据库中的数据,并且按照要求进行聚合. MongoDB提供了三种执行聚合的方法:Aggregation Pipleline,map-reduce功能和 Single Purpose Aggregation Operations 其中用来做聚合操作的几个函数是 aggregate(pipeline,options) 指定 group 的

mongodb aggregate and mapReduce

Aggregate MongoDB中聚合(aggregate)主要用于处理数据(诸如统计平均值,求和等),并返回计算后的数据结果.有点类似sql语句中的 count(*) 语法如下: db.collection.aggregate() db.collection.aggregate(pipeline,options) db.runCommand({ aggregate: "<collection>", pipeline: [ <stage>, <...&g

基于MongoDB分布式存储进行MapReduce并行查询

中介绍了如何基于Mongodb进行关系型数据的分布式存储,有了存储就会牵扯到查询.虽然用普通的方式也可以进行查询,但今天要介绍的是如何使用MONGODB中提供的MapReduce功能进行查询.      有关MongoDb的MapReduce之前我写过一篇文章 Mongodb Mapreduce 初窥, 今天介绍如何基于sharding机制进行mapreduce查询.在MongoDB的官方文档中,这么一句话: Sharded Environments      In sharded enviro

MongoDB中的group

在Mongodb的查询中,有类似于SQL中group by功能的group函数.两者的功能有些类似,但是区别也是比较明显的. 对于SQL来说,group by的作用就是安装依据列来将数据表中的记录分成一个个的组,而查询结果中,只能Select出来Group BY中含有的列,或者使用了聚合函数(sum,count,avg,max,min)的其它列.并且只能在数值类型上的列上使用聚合函数. 但是,在Mongodb中,我们可以在结果中显示既非Group by中的列,又没有使用聚合函数的列.这样,我们就

JAVA-查看MongoDB中的数据(包含List集合)

package com.xinsight.server; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.List; import com.mongodb.BasicDBObject; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mo