pymongo,map_reduce结果与mongo命令行不一样

时间:2015-08-03 08:24:50

标签: python mongodb

我是mongodb的新手,但这只是我的简单测试。 不幸的是,使用相同的map / reduce函数,我从mongo命令行和pymongo得到不同的结果...... Pymongo是3.0.3,mongodb是3.0

以下是命令行的操作:

map = function(){
... var date = new Date('2015-07-30');
... emit(date,this)
... }
function (){
var date = new Date('2015-07-30');
emit(date,this)
}

reduce = function(key, values){
... var sum = {'new':0,'act':0,'channel_new':{},'ver_new':{},'channel_ver_new':{}};
... values.forEach(function(doc){
... sum.new += doc.new;
... sum.act += doc.act;
... var category = {"channel_new":1,"ver_new":1,"channel_ver_new":1};
... for(var item in category)
... {
...   var t = Object.keys(doc[item]);
...   for(var i in t){
...    if(Object.keys(sum[item]).indexOf(t[i])!=-1){
...     sum[item][t[i]] += doc[item][t[i]];
...    }else{
...     sum[item][t[i]] = doc[item][t[i]];
...    }
...   }
... }
... });
... return sum;
... }
function (key, values){
var sum = {'new':0,'act':0,'channel_new':{},'ver_new':{},'channel_ver_new':{}};
values.forEach(function(doc){
sum.new += doc.new;
sum.act += doc.act;
var category = {"channel_new":1,"ver_new":1,"channel_ver_new":1};
for(var item in category)
{
  var t = Object.keys(doc[item]);
  for(var i in t){
   if(Object.keys(sum[item]).indexOf(t[i])!=-1){
    sum[item][t[i]] += doc[item][t[i]];
   }else{
    sum[item][t[i]] = doc[item][t[i]];
   }
  }
}
});
return sum;
}
db.daily.mapReduce(map,reduce,{out:"wnitest"})
{
        "result" : "wnitest",
        "timeMillis" : 12,
        "counts" : {
                "input" : 2,
                "emit" : 2,
                "reduce" : 1,
                "output" : 1
        },
        "ok" : 1
}

结果如下:

db.daily.find()
{ "_id" : ObjectId("55bef40cf6d9e26e37e3e37b"), "date" : ISODate("2015-07-06T00:00:00Z"), "new" : 1,
 "channel_ver_new" : { "111_0500_00*#*0\uff0E9\uff0E0" : 2 }, "ver_new" : { "0\uff0E9\uff0E0" : 2 },
 "channel_new" : { "111_0500_00" : 2 } }
{ "_id" : ObjectId("55bef40cf6d9e26e37e3e37d"), "date" : ISODate("2015-07-07T00:00:00Z"), "new" : 2,
 "channel_ver_new" : { "111_0500_00*#*1\uff0E0\uff0E0" : 3 }, "ver_new" : { "1\uff0E0\uff0E0" : 3 },
 "channel_new" : { "111_0500_00" : 3 } }

db.wnitest.find()
{ "_id" : ISODate("2015-07-30T00:00:00Z"), "value" : { "new" : 3, "act" : NaN, "channel_new" : { "11
1_0500_00" : 5 }, "ver_new" : { "0\uff0E9\uff0E0" : 2, "1\uff0E0\uff0E0" : 3 }, "channel_ver_new" :
{ "111_0500_00*#*0\uff0E9\uff0E0" : 2, "111_0500_00*#*1\uff0E0\uff0E0" : 3 } } }
>

这是我的python代码:

mapper = Code("""function(){
var date = new Date('2015-7-30');
emit(date,this);
}""")
reducer = Code("""function(key, values){
var sum = {"new":0,"act":0,"channel_new":{},"ver_new":{},"channel_ver_new":{}};
values.forEach(function(doc){
sum.new += doc.new;
sum.act += doc.act;
var category = {"channel_new":1,"ver_new":1,"channel_ver_new":1};
for(var item in category)
{
  var t = Object.keys(doc[item]);
  for(var i in t){
   if(Object.keys(sum[item]).indexOf(t[i])!=-1){
    sum[item][t[i]] += doc[item][t[i]];
   }else{
    sum[item][t[i]] = doc[item][t[i]];
   }
  }
}
});
return sum;
}
    """)
db.daily.map_reduce(mapper,reducer,'weekly')

Here is result:

> db.weekly.find()
{ "_id" : ISODate("2015-07-29T16:00:00Z"), "value" : { "_id" : ObjectId("55bef4eaf6d9e26e37e3e380"),
 "date" : ISODate("2015-07-06T00:00:00Z"), "new" : 1, "channel_ver_new" : { "111_0500_00*#*0\uff0E9\
uff0E0" : 2 }, "ver_new" : { "0\uff0E9\uff0E0" : 2 }, "channel_new" : { "111_0500_00" : 2 } } }
>

这是对pymongo的map_reduce:

的回应
{u'timing': {u'total': 59, u'mapTime': 0, u'emitLoop': 57, u'mode': u'mixed', u'reduceTime': 0}, u'counts': {u'input': 1, u'reduce': 0, u'emit': 1, u'output': 1}, u'timeMillis': 59, u'ok': 1.0, u'result': u'weekly'}

reduce是0,为什么?

1 个答案:

答案 0 :(得分:0)

我不认为这是python驱动程序的任何错误,只是首先没有正确设置reduce函数。

为了对所有可能键的值求和,那么您的代码看起来应该更像这样:

var mapper  = function() {
    delete this.date;
    emit(date,this);
};

var reducer = function(key,values) {
    var reduced = { 
        "new": 0, 
        "channel_new": {}, 
        "ver_new": {}, 
        "channel_ver_new": {} 
    };

    values.forEach(function(value) {
        reduced.new += value.new;

        Object.keys(reduced).filter(function(key) {
            return key != "new";
        }).forEach(function(key){
            if (value.hasOwnProperty(key)) {
                Object.keys(value[key]).forEach(function(iKey) {
                    if (!reduced[key].hasOwnProperty(ikey))
                        reduced[key][ikey] = 0;
                    reduced[key][ikey] += value[key][ikey];
                })
            }
        });
    });

    return reduced;
};

var options = {
    "out": { "inline": 1 },
    "scope": { "date": new Date("2015-07-27") },
    "query": { 
        "date": { 
            "$gte": new Date("2015-07-27"), "$lt": new Date("2015-08-03")
        }
    }
}

db.daily.mapReduce(mapper,reducer,options);

在给定查询范围选择的情况下,它可以正确地遍历所有元素和聚合。