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获取标准北京时间的方法
Mar 24 Python
Django框架教程之正则表达式URL误区详解
Jan 28 Python
PyQt5每天必学之布局管理
Apr 19 Python
Python json模块dumps、loads操作示例
Sep 06 Python
对Python发送带header的http请求方法详解
Jan 02 Python
python调用外部程序的实操步骤
Mar 04 Python
Python符号计算之实现函数极限的方法
Jul 15 Python
python+logging+yaml实现日志分割
Jul 22 Python
Python类中的魔法方法之 __slots__原理解析
Aug 26 Python
python 操作mysql数据中fetchone()和fetchall()方式
May 15 Python
详解pycharm2020.1.1专业版安装指南(推荐)
Aug 07 Python
Pycharm新手使用教程(图文详解)
Sep 17 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
是否存在第一台收音机的说法
2021/03/01 无线电
给初学PHP的5个入手程序
2006/11/23 PHP
谷歌音乐搜索栏的提示功能php修正代码
2011/05/09 PHP
PHP实现将几张照片拼接到一起的合成图片功能【便于整体打印输出】
2017/11/14 PHP
Ajax一统天下之Dojo整合篇
2007/03/24 Javascript
获取网站跟路径的javascript代码(站点及虚拟目录)
2009/10/20 Javascript
jquery的Tooltip插件 qtip使用详细说明
2010/09/08 Javascript
基于jquery的用鼠标画出可移动的div
2012/09/06 Javascript
解析Jquery的LigerUI如何实现文件上传
2013/07/09 Javascript
document.execCommand()的用法小结
2014/01/08 Javascript
javascript数据结构之双链表插入排序实例详解
2015/11/25 Javascript
JavaScript实现图片自动加载的瀑布流效果
2016/04/11 Javascript
jsp 自动编译机制详细介绍
2016/12/01 Javascript
推荐三款不错的图片压缩上传插件(webuploader、localResizeIMG4、LUploader)
2017/04/21 Javascript
详解Javascript获取缓存和清除缓存API
2017/05/25 Javascript
vue input 输入校验字母数字组合且长度小于30的实现代码
2018/05/16 Javascript
Vue商品控件与购物车联动效果的实例代码
2019/07/21 Javascript
解决layer 关闭当前弹窗 关闭遮罩层 input值获取不到的问题
2019/09/25 Javascript
Vue+Element实现网页版个人简历系统(推荐)
2019/12/31 Javascript
Python函数嵌套实例
2014/09/23 Python
Python open()文件处理使用介绍
2014/11/30 Python
PyQt5每天必学之拖放事件
2020/08/27 Python
Pycharm debug调试时带参数过程解析
2020/02/03 Python
CSS3线性渐变简单实现以及该属性在浏览器中的不同
2012/12/12 HTML / CSS
英国领先的名牌服装折扣零售商:Brown Bag Clothing
2019/01/08 全球购物
.net面试题
2016/09/17 面试题
计算机科学与技术应届生求职信
2013/11/07 职场文书
自我鉴定写作要点
2014/01/17 职场文书
公积金接收函格式
2015/01/30 职场文书
销售合作意向书范本
2015/05/08 职场文书
2015年酒店年度工作总结
2015/05/23 职场文书
计算机实训心得体会
2016/01/14 职场文书
区域销售大会开幕词
2016/03/04 职场文书
三好学生竞选稿范文
2019/08/21 职场文书
SpringBoot工程下使用OpenFeign的坑及解决
2021/07/02 Java/Android
分享很少见很有用的SQL功能CORRESPONDING
2022/08/05 MySQL