MapReduce
1. 概述
MapReduce 是 Mongodb 中的高级聚合工具, count、distinct、group 能做的事 MapReduce 都能做.
除此外, 它还可以并行化到多个服务器上. 它将聚合运算拆分, 再将各个部分发送到不同的服务器上, 让每台服务器都完成一部分, 当所有服务器都完成的时候, 再把结果汇集起来形成最终完整的结果.
MapReduce 十分强大, 但其代价就是牺牲性能, 所以千万不要用在"实时"的操作中, 可以作为后台任务来运行 MapReduce, 将结果缓存在另一个集合中, 当"实时"操作发生时, 我们从这个缓存集合中进行查询.
2. 实例
MapReduce 直接解释起来可能比较麻烦, 通过一个实例来学习是最好不过了, 这里参考别人的文章, 是的, 这个实例, 我只是个搬运工...原文传送门
语法:
测试数据:
现在我要统计同一 age 的 name, 也就是像如下的结果:
第一步是写 Map (映射)函数, 可以简单的理解成分组吧~
emit 的第一个参数是 key, 就是分组的依据, 参考 group 中的 key 的功能, 这是自然是 age 了, 后面一个是 value, 就是要统计的数据, 可以是 JSON 对象. this 表示的是对当前文档的引用.
这样 m 就会把送过来的数据根据 Map 函数中定义的 key 进行分组了, 组中的元素就是 Map 函数中定义的 value, 可以想象成如下结构:
组中的 key 其实就是 age 的值了, values 是个数组, 数组内的成员都有相同的 age !!
第二步就是简化了, 编写 reduce 函数:
reduce 函数会处理每一个分组, 参数就是我们想像分组里的 key 和 values.
这里 reduce 函数只是简单的把 key 和 values 包装了一下, 然后返回一个对象, 对象结构正好和我们想象的相符:
然后, 还可以编写 finalize 函数对 reduce 的返回值做最后处理:
这里的 key 还是上面的 key, 也就是还是 age, rval 是 reduce 的返回值, 所以 rval 的一个实例如: {age: 0, names: ['name_6', 'name_12', 'name_18']},
这里判断 key 是不是 0, 如果是, 就在 rval 对象上加 msg 属性, 显然也可以判断 rval.age == 0, 因为 key 和 rval.age 是相等的嘛~~
最终, 就是调用 MpaReduce 工具了:
最终返回的 t_age_names 集合中的文档包含两个键 _id 和 value:
_id, 保存上面的 key, 这个例子中就是 age
value, 保存最终运算出的结果, 如 {'age': 3, 'name': ['name_1', 'name_2']}
Last updated