我发现了一堆map_reduce教程,但它们似乎都没有“where”子句或其他任何方式来排除正在考虑的文件/记录。我正在研究一个看似简单的查询。我有一个带有时间戳,IP地址和活动ID的事件的基本日志文件。我想获得给定广告系列在给定时间戳范围内的唯一身份用户数。听起来很简单!
我构建了一个类似这样的查询对象:
{'ts': {'$gt': 1345840456, '$lt': 2345762454}, 'cid': '2636518'}
有了这个,我尝试了两件事,一件使用distinct,另一件使用map_reduce:
鲜明
db.alpha2.find(query).distinct('ip').count()
在mongo shell中,你可以将查询作为distinct函数的第二个参数,它可以在那里工作,但我读过你不能在pymongo中这样做。
Map_reduce
map = Code("function () {"
" emit(this.ip, 1);"
"}")
reduce = Code("function (key, values) {"
" var total = 0;"
" for (var i = 0; i < values.length; i++) {"
" total += values[i];"
" }"
" return total;"
"}")
totaluniqueimp = db.alpha2.map_reduce(map, reduce, "myresults").count();
(我意识到reduce函数正在做我不需要的东西,我从演示中获取它)。这很好,但不使用我的“where”参数。我试试这个:
totaluniqueimp = db.alpha2.find(query).map_reduce(map, reduce, "myresults").count();`
我收到了这个错误:
AttributeError: 'Cursor' object has no attribute 'map_reduce'
结论
基本上,这就是我在mysql中尝试做的事情:
select count(*) from records where ts<1000 and ts>900 and campaignid=234 group by ipaddress
看起来很简单!你是如何在mongo中做到这一点的?
根据Dmitry在下面的回答,我能够解决(并简化)我的解决方案(这是我能做到的那么简单吗?):
#query is an object that was built above this
map = Code("function () { emit(this.ip, 1);}")
reduce = Code("function (key, values) {return 1;}")
totaluniqueimp = collection.map_reduce(map, reduce, "myresults", query=query).count();
谢谢德米特里!
答案 0 :(得分:4)
你可以试试这个:
totaluniqueimp = db.alpha2.map_reduce(map, reduce, {
out: "myresults",
query: {'ts': {'$gt': 1345840456, '$lt': 2345762454}, 'cid': '2636518'}
}).count();
更新:上面的语句适用于mongo shell。在pymongo中,您应该将查询添加为第四个参数:
totaluniqueimp = db.alpha2.map_reduce(map, reduce, "myresults", query={'ts': {'$gt': 1345840456, '$lt': 2345762454}, 'cid': '2636518'})
可以找到详细的文档here。
答案 1 :(得分:0)
不确定这是否可以通过pymongo,手册指出它应该是,但是在mongoDB shell中你有一个group()函数,这将很容易让你在你的问题中重写SQL:
select count(*)
from records
where ts<1000
and ts>900
and campaignid=234
group by ipaddress;
如:
db. alpha2.group(
{ cond: { 'ts': {'$gt': 900, '$lt': 1000}, 'campaignid': '234' }
, key: { "ipaddress" : 1 }
, initial: {count : 0}
, reduce: function(doc, out){ out.count++}
}
);