我是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,为什么?
答案 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);
在给定查询范围选择的情况下,它可以正确地遍历所有元素和聚合。