pymongo中group by的操作方法教程


Posted in Python onMarch 22, 2019

前言

使用 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 默认返回浮点数。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
跟老齐学Python之for循环语句
Oct 02 Python
python中while循环语句用法简单实例
May 07 Python
Python+django实现文件下载
Jan 17 Python
python tkinter实现彩球碰撞屏保
Jul 30 Python
简单了解python 生成器 列表推导式 生成器表达式
Aug 22 Python
Python字符串格式化输出代码实例
Nov 22 Python
Python sqlalchemy时间戳及密码管理实现代码详解
Aug 01 Python
Python经纬度坐标转换为距离及角度的实现
Nov 01 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
Nov 05 Python
粗暴解决CUDA out of memory的问题
May 22 Python
Elasticsearch 聚合查询和排序
Apr 19 Python
Golang Web 框架Iris安装部署
Aug 14 Python
Python常用特殊方法实例总结
Mar 22 #Python
pymongo中聚合查询的使用方法
Mar 22 #Python
OpenCV HSV颜色识别及HSV基本颜色分量范围
Mar 22 #Python
基于OpenCV python3实现证件照换背景的方法
Mar 22 #Python
详解Python给照片换底色(蓝底换红底)
Mar 22 #Python
详解python-图像处理(映射变换)
Mar 22 #Python
python中如何使用分步式进程计算详解
Mar 22 #Python
You might like
php Ajax乱码
2008/04/09 PHP
PHP实现通过get方式识别用户发送邮件的方法
2015/07/16 PHP
详谈PHP编码转换问题
2015/07/28 PHP
TP5框架实现上传多张图片的方法分析
2020/03/29 PHP
玩转jQuery按钮 请告诉我你最喜欢哪些?
2012/01/08 Javascript
jQuery-onload让第一次页面加载时图片是淡入方式显示
2012/05/23 Javascript
Package.js  现代化的JavaScript项目make工具
2012/05/23 Javascript
jQuery基于当前元素进行下一步的遍历
2014/05/20 Javascript
jquery模拟alert的弹窗插件
2015/07/31 Javascript
继续学习javascript闭包
2015/12/03 Javascript
深入理解bootstrap框架之第二章整体架构
2016/10/09 Javascript
详解nodejs微信公众号开发——3.封装消息响应模块
2017/04/10 NodeJs
浅析JS中常用类型转换及运算符表达式
2017/07/23 Javascript
javascript中的隐式调用
2018/02/10 Javascript
Vue.js自定义事件的表单输入组件方法
2018/03/08 Javascript
JQuery样式操作、click事件以及索引值-选项卡应用示例
2019/05/14 jQuery
基于vue 实现表单中password输入的显示与隐藏功能
2019/07/19 Javascript
js+html+css实现手动轮播和自动轮播
2020/12/30 Javascript
[50:28]LGD女子学院第三期 DOTA2复仇之魂教学
2013/12/24 DOTA
python正则表达式re模块详解
2014/06/25 Python
详解Python3 对象组合zip()和回退方式*zip
2019/05/15 Python
给你一面国旗 教你用python画中国国旗
2019/09/24 Python
python3 实现函数写文件路径的正确方法
2019/11/27 Python
Python实现变声器功能(萝莉音御姐音)
2019/12/05 Python
在Pytorch中计算自己模型的FLOPs方式
2019/12/30 Python
基于PyTorch的permute和reshape/view的区别介绍
2020/06/18 Python
matplotlib对象拾取事件处理的实现
2021/01/14 Python
Pandas数据分析的一些常用小技巧
2021/02/07 Python
详解CSS3中Media Queries的相关使用
2015/07/17 HTML / CSS
前端隐藏出边界内容的实现方法
2016/04/14 HTML / CSS
关于iframe跨域使用postMessage的实现
2019/10/29 HTML / CSS
党校培训思想汇报
2014/01/03 职场文书
伊琍体标语
2014/06/25 职场文书
生产现场禁烟通知
2015/04/23 职场文书
2015年度物流工作总结
2015/04/30 职场文书
Ajax请求超时与网络异常处理图文详解
2021/05/23 Javascript