在MongoDB中使用Map/Reduce
在mongodb的map-reduce是一个针对大数据的数据处理范式,可将大量数据浓缩成有用的聚合结果。对于map-reduce操作, MongoDB 提供mapReduce 数据库命令,这个命令意味什么呢?
这个命令有两个初始输入, mapper 函数和reducer 函数.
一个Mapper函数是开始读取数据集合,然后建立一个Map,Map的Key是我们希望依据其分组的数据字段,这对key/value然后送入一个Reducer函数, 这时将处理值values. MongoDB 支持在一个分区的集合上实现map-reduce操作.
下面看看一个数据的集合,模拟输入如下:
{
name: foo,
price: 9
},
{
name: foo,
price: 12
},
{
name: bar,
price: 8
},
{
name: baz,
price: 3
},
{
name: baz,
price: 5
}
{
name: baz,
price: 8
}
现在我们需要根据名称name匹配排序价格. 我们mapper和 reducer处理输出如下:
foo [9,12]
bar [8]
baz [3,5,8]
在上面结果我们看到相同名称的产品按照其价格排序了。
下面看看是如何工作的?
在mongodb中 map-reduce是使用javascript调用的. 首先我们需要创建一个javascript 函数来实现mapping ,在map函数中,我们针对key有一个emit方法. Mapping完成后我们需要函数reduce. 用来将结果放在一起然后综合它们。
看看代码:
Javascript function for mapping:
var map = function(){
......
emit();
}
javascript function for reduce:
var reduce = function(key, value){
return {result1: one, result2: two};
}
如果我们完成了mapping和reducing后,如何针对一个集合运行查询呢?
db.collection_name.mapReduce(map, reduce);
上面我们使用了mongodb提供的mapreduce方法. map和reduce作为该方法两个参数.
上面是简单情况,假设我们有一个集合名称test. 我们需要将这个集合map-reduce到另外一个名为mapped_collection的集合.
我们需要在上面代码中提供输出路径。如下:
db.test.mapReduce(map, reduce, { out: "mapped_collection" });
map-reduce操作能够将结果写入到一个集合或返回单一结果,如果输出到集合,我们能够对同一个集合实现一系列map-reduce操作。实现merge replace reduce等操作。
当我们返回单个map reduce结果,这个结果文档应该受BSON文档大小限制,当前是16M。
下面我们对图书进行分类统计。小于250页的归为Story,而大于250页归为Novel.
数据样本如下:
book1 = {name : "2 states", pages : 100}
book2 = {name : "The Unstable Earth", pages : 200}
book3 = {name : "Eragon", pages : 300}
book4 = {name : "Inheritence", pages : 400}
db.books.save(book1)
db.books.save(book2)
db.books.save(book3)
db.books.save(book4)
map代码如下:
var map = function() {
var category;
if ( this.pages >250 )
category = 'Novel';
else
category = "Story";
emit(category, {name: this.name});
};
Reducer代码如下:
var reduce = function(key, values) {
var sum = 0;
values.forEach(function(doc) {
sum += 1;
});
return {books: sum};
};
针对一个集合运行mapreduce。
var count = db.books.mapReduce(map, reduce, {out: "book_results"});
db[count.result].find()
如果一切正常,输出结果如下:
{ "_id" : "Novel", "value" : { "books" : 2 } }
{ "_id" : "Story", "value" : { "books" : 2} }