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利用hook技术破解https的实例代码
Mar 25 Python
Python抓取Discuz!用户名脚本代码
Dec 30 Python
python使用rabbitmq实现网络爬虫示例
Feb 20 Python
Python深入学习之对象的属性
Aug 31 Python
python避免死锁方法实例分析
Jun 04 Python
使用Python通过win32 COM打开Excel并添加Sheet的方法
May 02 Python
python验证码图片处理(二值化)
Nov 01 Python
详解字符串在Python内部是如何省内存的
Feb 03 Python
python实现感知机模型的示例
Sep 30 Python
Python常用扩展插件使用教程解析
Nov 02 Python
关于Numpy之repeat、tile的用法总结
Jun 02 Python
python使用PySimpleGUI设置进度条及控件使用
Jun 10 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性能分析工具XHProf安装使用教程
2015/05/13 PHP
PHP中文竖排转换实现方法
2015/10/23 PHP
CI框架中类的自动加载问题分析
2016/11/21 PHP
PHP数组与字符串互相转换实例
2020/05/05 PHP
实例化php类时传参的方法分析
2020/06/05 PHP
一个js封装的不错的选项卡效果代码
2008/02/15 Javascript
JavaScript 开发中规范性的一点感想
2009/06/23 Javascript
jquery 表格分页等操作实现代码(pagedown,pageup)
2010/04/11 Javascript
非常强大的 jQuery.AsyncBox 弹出对话框插件
2011/08/29 Javascript
JavaScript异步编程:异步数据收集的具体方法
2013/08/19 Javascript
yepnope.js使用详解及示例分享
2014/06/23 Javascript
解析javascript中鼠标滚轮事件
2015/05/26 Javascript
javascript实现删除前弹出确认框
2015/06/04 Javascript
js实现跨域的方法实例详解
2015/06/24 Javascript
微信小程序 wxapp导航 navigator详解
2016/10/31 Javascript
js模糊查询实例分享
2016/12/26 Javascript
浅谈js算法和流程控制
2016/12/29 Javascript
微信小程序之picker日期和时间选择器
2017/02/09 Javascript
JavaScript实现的冒泡排序法及统计相邻数交换次数示例
2017/04/26 Javascript
ES6新增数据结构WeakSet的用法详解
2017/08/07 Javascript
让bootstrap的carousel支持滑动滚屏的实现代码
2017/11/27 Javascript
Vue.js 2.x之组件的定义和注册图文详解
2018/06/19 Javascript
JS中创建自定义类型的常用模式总结【工厂模式,构造函数模式,原型模式,动态原型模式等】
2019/01/19 Javascript
Angular8 Http拦截器简单使用教程
2019/08/20 Javascript
Python3 实现文件批量重命名示例代码
2019/06/03 Python
VS2019+python3.7+opencv4.1+tensorflow1.13配置详解
2020/04/16 Python
英国最大的百货公司:Harrods
2016/08/18 全球购物
英国最大的在线时尚眼镜店:Eyewearbrands
2019/03/12 全球购物
校庆接待方案
2014/03/18 职场文书
超市仓管员岗位职责范本
2014/09/18 职场文书
2014年党员自我评议总结
2014/09/23 职场文书
党员贯彻十八大精神思想汇报范文
2014/10/25 职场文书
2015年小学教科研工作总结
2015/07/20 职场文书
2015年党务工作者个人工作总结
2015/10/22 职场文书
2016年教师学习教师法心得体会
2016/01/20 职场文书
MySQL 发生同步延迟时Seconds_Behind_Master还为0的原因
2021/06/21 MySQL