MongoDB管理与开发精要《红丸出品》8 MapReduce

第八章 MapReduce

MongoDBMapReduce相当于Mysql中的"group by",所以在MongoDB上使用 Map/Reduce 进行并行"统计"很容易。

 

使用MapReduce要实现两个函数 Map函数和Reduce函数,Map函数调用emit(key, value),遍历collection中所有的记录,将keyvalue传递给Reduce函数进行处理。Map函数和Reduce函数可以使用JavaScript来实现,可以通过db.runCommandmapReduce命令来执行一个MapReduce的操作:

 

db.runCommand(

 { mapreduce : <collection>,

   map : <mapfunction>,

   reduce : <reducefunction>

   [, query : <query filter object>]

   [, sort : <sorts the input objects using this key. Useful for optimization, like sorting by the emit key for fewer reduces>]

   [, limit : <number of objects to return from collection>]

   [, out : <see output options below>]

   [, keeptemp: <true|false>]

   [, finalize : <finalizefunction>]

   [, scope : <object where fields go into javascript global scope >]

   [, verbose : true]

 }

);

参数说明:

mapreduce: 要操作的目标集合。

map: 映射函数 (生成键值对序列,作为 reduce函数参数)

reduce: 统计函数。

query: 目标记录过滤。

sort: 目标记录排序。

limit: 限制目标记录数量。

out: 统计结果存放集合 (不指定则使用临时集合,在客户端断开后自动删除)

keeptemp: 是否保留临时集合。

finalize: 最终处理函数 ( reduce返回结果进行最终整理后存入结果集合)

scope: mapreducefinalize导入外部变量。

verbose: 显示详细的时间统计信息。

 

下面我们先准备一些数据:

> db.students.insert({classid:1, age:14, name:'Tom'})

> db.students.insert({classid:1, age:12, name:'Jacky'})

> db.students.insert({classid:2, age:16, name:'Lily'})

> db.students.insert({classid:2, age:9, name:'Tony'})

> db.students.insert({classid:2, age:19, name:'Harry'})

> db.students.insert({classid:2, age:13, name:'Vincent'})

> db.students.insert({classid:1, age:14, name:'Bill'})

> db.students.insert({classid:2, age:17, name:'Bruce'})

接下来,我们将演示如何统计1班和2班的学生数量

8.1 Map

Map 函数必须调用 emit(key, value)返回键值对,使用 this访问当前待处理的 Document

> m = function() { emit(this.classid, 1) }

function () {

    emit(this.classid, 1);

}

value 可以使用 JSON Object传递 (支持多个属性值)。例如:

emit(this.classid, {count:1})

8.2 Reduce

Reduce函数接收的参数类似 Group效果,将 Map返回的键值序列组合成 { key, [value1, value2, value3, value...] }传递给 reduce

> r = function(key, values) {

... var x = 0;

... values.forEach(function(v) { x += v });

... return x;

... }

function (key, values) {

    var x = 0;

    values.forEach(function (v) {x += v;});

    return x;

}

Reduce 函数对这些 values进行 "统计"操作,返回结果可以使用 JSON Object

8.3 Result

> res = db.runCommand({

... mapreduce:"students",

... map:m,

... reduce:r,

... out:"students_res"

... });

{

        "result" : "students_res",

        "timeMillis" : 1587,

        "counts" : {

                "input" : 8,

                "emit" : 8,

                "output" : 2

        },

        "ok" : 1

}

> db.students_res.find()

{ "_id" : 1, "value" : 3 }

{ "_id" : 2, "value" : 5 }

mapReduce() 将结果存储在 "students_res" 表中。

8.4 Finalize

利用 finalize() 我们可以对 reduce() 的结果做进一步处理。

> f = function(key, value) { return {classid:key, count:value}; }

function (key, value) {

    return {classid:key, count:value};

}

>

我们再重新计算一次,看看返回的结果:

> res = db.runCommand({

... mapreduce:"students",

... map:m,

... reduce:r,

... out:"students_res",

... finalize:f

... });

{

        "result" : "students_res",

        "timeMillis" : 804,

        "counts" : {

                "input" : 8,

                "emit" : 8,

                "output" : 2

        },

        "ok" : 1

}

> db.students_res.find()

{ "_id" : 1, "value" : { "classid" : 1, "count" : 3 } }

{ "_id" : 2, "value" : { "classid" : 2, "count" : 5 } }

列名变与 “classid””count”了,这样的列表更容易理解。

8.5 Options

我们还可以添加更多的控制细节。

> res = db.runCommand({

... mapreduce:"students",

... map:m,

... reduce:r,

... out:"students_res",

... finalize:f,

... query:{age:{$lt:10}}

... });

{

        "result" : "students_res",

        "timeMillis" : 358,

        "counts" : {

                "input" : 1,

                "emit" : 1,

                "output" : 1

        },

        "ok" : 1

}

> db.students_res.find();

{ "_id" : 2, "value" : { "classid" : 2, "count" : 1 } }

可以看到先进行了过滤,只取age<10的数据,然后再进行统计,所以就没有1班的统计数据了。
-------------------------------------------------------------------
《MongoDB管理与开发精要》、《Redis实战》作者
ChinaUnix.net专家
http://cdhongwan.blog.chinaunix.net
@CD红丸           http://weibo.com/u/2446082491
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值