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 相关文章推荐
仅用50行代码实现一个Python编写的计算器的教程
Apr 17 Python
使用Python3制作TCP端口扫描器
Apr 17 Python
python 用lambda函数替换for循环的方法
Jun 09 Python
python3对拉勾数据进行可视化分析的方法详解
Apr 03 Python
Python3模拟curl发送post请求操作示例
May 03 Python
Python的log日志功能及设置方法
Jul 11 Python
Python多线程及其基本使用方法实例分析
Oct 29 Python
Python的缺点和劣势分析
Nov 19 Python
利用python读取YUV文件 转RGB 8bit/10bit通用
Dec 09 Python
Python代码中如何读取键盘录入的值
May 27 Python
keras做CNN的训练误差loss的下降操作
Jun 22 Python
详解Python+OpenCV进行基础的图像操作
Feb 15 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入门学习知识点二 PHP简单的分页过程与原理
2011/07/14 PHP
ThinkPHP 防止表单重复提交的方法
2011/08/08 PHP
让iframe自适应高度(支持XHTML,支持FF)
2007/07/24 Javascript
动态加载script文件的两种方法
2013/08/15 Javascript
jQuery中index()的用法分析
2014/09/05 Javascript
详解AngularJS中的http拦截
2016/02/09 Javascript
利用AngularJs实现京东首页轮播图效果
2016/09/08 Javascript
Bootstrap按钮功能之查询按钮和重置按钮
2016/10/26 Javascript
求js数组的最大值和最小值的四种方法
2017/03/03 Javascript
jQuery插件zTree实现更新根节点中第i个节点名称的方法示例
2017/03/08 Javascript
浅谈Angular6的服务和依赖注入
2018/06/27 Javascript
angular6.0开发教程之如何安装angular6.0框架
2018/06/29 Javascript
微信小程序列表中item左滑删除功能
2018/11/07 Javascript
原生js实现获取form表单数据代码实例
2019/03/27 Javascript
Vue render函数实战之实现tabs选项卡组件
2019/04/22 Javascript
使用vue for时为什么要key【推荐】
2019/07/11 Javascript
Vue3项目打包后部署到服务器 请求不到后台接口解决方法
2020/02/06 Javascript
vue-路由精讲 二级路由和三级路由的作用
2020/08/06 Javascript
vue 函数调用加括号与不加括号的区别
2020/10/29 Javascript
[01:22:28]DOTA2-DPC中国联赛 正赛 SAG vs RNG BO3 第一场 1月18日
2021/03/11 DOTA
python2.7删除文件夹和删除文件代码实例
2013/12/18 Python
Python如何import文件夹下的文件(实现方法)
2017/01/24 Python
Python中生成Epoch的方法
2017/04/26 Python
使用python判断jpeg图片的完整性实例
2019/06/10 Python
用Python实现将一张图片分成9宫格的示例
2019/07/05 Python
python3连接MySQL8.0的两种方式
2020/02/17 Python
W Hamond官网:始于1979年的钻石专家
2020/07/20 全球购物
《月球之谜》教学反思
2014/04/10 职场文书
人事行政经理岗位职责
2014/06/18 职场文书
篮球社团活动总结
2014/06/27 职场文书
2014年预备党员端正入党动机思想汇报
2014/09/13 职场文书
家庭财产分割协议书范本
2014/11/24 职场文书
总经理岗位职责
2015/02/04 职场文书
2015年党风建设工作总结
2015/04/29 职场文书
公司环境卫生管理制度
2015/08/05 职场文书
Go语言编译原理之源码调试
2022/08/05 Golang