NoSQL专题

在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} }

 

MongoDB专题与教程

Hadoop专题