2013-10-04 2 views
0

Я попытался использовать агрегирование MapReduce дважды, чтобы получить уникальный номер пользователя в месяц.получить неопределенное значение в mongodb MapReduce

Первая функция MR разработать коллекцию mr_buyer_payment, как это:

{ "_id" : { "u" : "01329f19-27b0-435b-9ca1-450984024a31", "tid" : ISODate("2013-09-01T00:00:00Z") }, "value" : { "payment" : 38, "count_pay" : 1 } } 
{ "_id" : { "u" : "264dd104-b934-490b-988e-5822fd7970f6", "tid" : ISODate("2013-09-01T00:00:00Z") }, "value" : { "payment" : 4.99, "count_pay" : 1 } } 
{ "_id" : { "u" : "27bb8f72-a13e-4676-862c-02f41fea1bc0", "tid" : ISODate("2013-09-01T00:00:00Z") }, "value" : { "payment" : 11.98, "count_pay" : 2 } } 

Вторая функция MR хорошо работает с небольшим набором данных, но при запросе растет более чем 100 записей, он получает неверный результат, а некоторые значение - NaN.

Журнал отладки показывает некоторое значение в функции уменьшения, например v.payment, v.count_user стал неопределенным.

date:Sun Jun 30 2013 17:00:00 GMT-0700 (PDT) value:undefined/162/undefined 

И информация результата MR проводная:

{ 
    "result" : "mr_buyer_all", 
    "timeMillis" : 29, 
    "counts" : { 
     "input" : 167, 
     "emit" : 167, 
     "reduce" : 6, // it should be 3, as same as "output" number 
     "output" : 3 
    }, 
    "ok" : 1, 
} 

Это вторая функция MR:

db.mr_buyer_payment.mapReduce(
    function(){ 
     var key = this._id.tid; 
     var value = { 
      payment:this.value.payment, 
      count_pay:this.value.count_pay, 
      count_user:1 
     }; 
     if (value.count_pay>0) 
     { 
      print("date:"+key+" u:"+this._id.u+"value:"+value.payment+"/"+value.count_pay+"/"+value.count_user); 
      emit(key,value); 
     } 
    }, 
    function(key,values){ 
     var result = {revenue:0,count_pay:0,user:0}; 
     values.forEach(function(v){ 
      if (!v.count_user) 
      { 
       print("date:"+key+" "+"value:"+v.payment+"/"+v.count_pay+"/"+v.count_user); 
      } else 
      { 
       result.revenue += v.payment; 
       result.count_pay += v.count_pay; 
       result.user += v.count_user; 
      } 

     }); 
     return result; 
    }, 
    { 
     out:{replace:"mr_buyer_all"} 
    } 
) 

ответ

1

поддокумент в Уменьшите функцию следует использовать тот же формат, что и один в карте функция. Таким образом, решение таково:

function(key,values){ 
    // the following key must be as same as the object in map 
    var r = {payment:0,count_pay:0,count_user:0} 
    values.forEach(function(v){ 
     r.payment += v.payment; 
     r.count_pay += v.count_pay; 
     r.count_user += v.count_user; 
    }); 
    return r; 
},