前言
使用 pymongo 进行 group by 操作有两种基本方式,他们都是 mongodb 的原生命令,于 Collection 对象上调用。
def aggregate(self, pipeline, **kwargs): def group(self, key, condition, initial, reduce, finalize=None, **kwargs):
示例数据
演示用的数据为一个订单表,含有以下字段:
Order
_id: ObjectID
userid: int
itemid: int
amount: int
time: string
主要任务为:
- 统计某个时间区间内每个 userid 的订单数
- 统计某个时间区间内每组 (userid, itemid) 共售出多少 amount
即分别为:单键分组和多键分组
aggregate
聚合操作只接受一个列表类型的参数 —— pipeline。其每一个元素都是一步操作(stage)。全部可用的 stage 可参见:
https://docs.mongodb.com/manual/meta/aggregation-quick-reference/#stages
注意 pipline 里面的 stage 是有序且可重复的,mongodb 会顺序执行,因此一定要记得把像 $match 这样的 stage 放前面。
单键分组
start_time = '2010-10-10 00:00:00' end_time = '2010-10-10 23:59:59' match = { 'time': { '$gte': start_time, '$lte': end_time, } } groupby = 'userid' group = { '_id': "$%s" % (groupby if groupby else None), 'count': {'$sum': 1} } ret = collection.aggregate( [ {'$match': match}, {'$group': group}, ] ) > ret [{'_id': 123, 'count': 500}, ...]
$group 指定了返回数据的格式,其中 _id 字段是分组的键。
多键分组
groupby = ['itemid', 'userid'] group = { '_id': {key: ('$%s' % key) for key in groupby} or {'None': '$None'}, 'count': {'$sum': '$amount'} } ret = collection.aggregate( [ {'$match': match}, {'$group': group}, ] ) > ret [{'_id': {'itemid': 111, 'user_id': 123}, 'count': 100}, ...]
这里与单键分组的区别仅在于 _id 的类型,改成了一个字典,从而允许多键组合。
为了提高通用性,建议始终使用字典的格式。
另外,既然字符串和字典都可以做键,那么列表行不行呢?答案是不行,列表里的元素,(如 '$userid') 并不会被自动识别为字段,而是仅作一般字符串处理。
最后关于 aggregate 中可用的运算操作符,可参见:
https://docs.mongodb.com/manual/reference/operator/aggregation/#accumulators
如其中的 $addToSet 也是颇有用处,可以用来实现 “统计每个人都买过哪些 itemid” 这样的功能:
group = { '_id': {'userid': '$userid'}, 'dist_itemids': {'$addToSet': '$itemid'}, }
group
相较于 aggregate 的全能,group 是专门处理分组操作的一个命令,因此这个方法的参数也更明确,主要参数为:
- key list, 分组的键
- condition dict,过滤条件
- initial dict,初始值
- reduce string/bson.Code, js 的 reduce 函数
例:
key = ['userid', 'itemid'] condition = { 'time': { '$gte': start_time, '$lte': end_time, } } initial = {'count': 0} reducer = Code(""" function(obj, prev) { prev.count = prev.count + obj.amount } """) ret = collection.group(key, condition, initial, reducer) > ret [{'userid': 110, 'itemid': 123, 'count': 500.0}, ...]
这里的分组数据聚合,是通过 reduce 函数实现的,这个函数与 python 的 reduce 不同,它不需要返回值,而是直接修改 prev 参数即可,这个参数会自动代入下一次调用。这可能是 js 的实现。
须注意的是 js 默认返回浮点数。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
更新日志
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]