2013年2月3日 星期日

Map Reduce in MongoDB

1. 在程式內呼叫 mongodb 內建之 map reduce 的方法
 
from bson.code import Code 
# main logic
log_collection = getReadCollection('LOG')
mapper = Code(mapper_code)
reducer = Code(reducer_code)
output_collection = getReadCollection('PAGEVIEW')
results = hfd_collection.map_reduce(mapper, reducer, output_collection)
 
ps: mapper_code 及 reducer_code 是由 javascript 作為語言的程式碼片段字串, 例如
 
# mapper_code
function() {
 if (this.country=="US"){ 
         emit(this.number , {freq: this.freq})
  }
}
 
# reducer_code 
function reduce(key, values) {
     var total = 0;
     for (var i=0;  i< values.length ; i++ ) {
          total += values[i].freq;
     }
     return {freq: total}
}
 
2. 注意事項
 
最後產生的結果會如下格式:
{
   "_id" : key,
   "value" : { value }
}
 
而 key 即是 mapper_code 中 emit 函式的第一個參數 , 上例中最後運算的結果格式如下
{
  "_id" : u223686999,
  "value" : { "freq" : 30 }
}
 
然而若要讓 map reduce 以多個 key 為條件去做 aggregation ( google 關鍵字可下 : compound key + mongodb ) , 則可修正如下:
 
# mapper_code
function() {
 if (this.country=="US"){ 
         emit( { number: this.number ,date: this.date } , {freq: this.freq})
  }
}
則會產生
{
  "_id" : { 
     "number" : u862236699,
     "date" : ISODate("2013-01-31T00:00:00.0Z")
   }
  "value" : { "freq" : 30 }
}
 
Reference : http://cookbook.mongodb.org/patterns/unique_items_map_reduce/