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 23 Python
python分析nignx访问日志脚本分享
Feb 26 Python
Python虚拟环境virtualenv的安装与使用详解
May 28 Python
Python 修改列表中的元素方法
Jun 26 Python
Python设计模式之迭代器模式原理与用法实例分析
Jan 10 Python
python实现QQ邮箱/163邮箱的邮件发送
Jan 22 Python
python通过SSH登陆linux并操作的实现
Oct 10 Python
Jupyter notebook 启动闪退问题的解决
Apr 13 Python
Python如何将函数值赋给变量
Apr 28 Python
python实现录音功能(可随时停止录音)
Oct 26 Python
10个顶级Python实用库推荐
Mar 04 Python
基于Python实现股票收益率分析
Apr 02 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中运用http调用的GET和POST方法示例
2014/09/29 PHP
PHP中file_put_contents追加和换行的实现方法
2017/04/01 PHP
基于Laravel 多个中间件的执行顺序详解
2019/10/21 PHP
使两个iframe的高度与内容自适应,且相等
2006/11/20 Javascript
符合标准的js表单提交的代码
2007/09/13 Javascript
javascript 伪数组实现方法
2010/10/11 Javascript
ToolTips JQEURY插件之简洁小提示框效果
2011/11/19 Javascript
js实现点小图看大图效果的思路及示例代码
2013/10/28 Javascript
浏览器窗口加载和大小改变事件示例
2014/02/27 Javascript
JavaScript表单验证实例之验证表单项是否为空
2016/01/10 Javascript
JavaScript代码实现左右上下自动晃动自动移动
2016/04/08 Javascript
node.js学习之交互式解释器REPL详解
2016/12/08 Javascript
详解Vue.js入门环境搭建
2017/03/17 Javascript
vue中过滤器filter的讲解
2019/01/21 Javascript
layer弹出层自适应高度,垂直水平居中的实现
2019/09/16 Javascript
vue+webpack dev本地调试全局样式引用失效的解决方案
2019/11/12 Javascript
javascript利用canvas实现鼠标拖拽功能
2020/07/23 Javascript
微信小程序接入vant Weapp组件的详细步骤
2020/10/28 Javascript
vue 实现element-ui中的加载中状态
2020/11/11 Javascript
python实现的一个火车票转让信息采集器
2014/07/09 Python
对比Python中__getattr__和 __getattribute__获取属性的用法
2016/06/21 Python
Python中__slots__属性介绍与基本使用方法
2018/09/05 Python
python多任务之协程的使用详解
2019/08/26 Python
如何使用python传入不确定个数参数
2020/02/18 Python
Python常用扩展插件使用教程解析
2020/11/02 Python
HTML5无刷新改变当前url的代码
2017/03/15 HTML / CSS
NFL欧洲商店(德国):NFL Europe Shop DE
2018/11/03 全球购物
在印度上传处方,在线订购药品:Medlife
2019/03/28 全球购物
运动会通讯稿150字
2014/02/15 职场文书
秋季运动会演讲稿
2014/09/16 职场文书
重温入党誓词主持词
2015/06/29 职场文书
美德少年主要事迹材料
2015/11/04 职场文书
分享:关于学习的励志名言赏析
2019/08/16 职场文书
go结构体嵌套的切片数组操作
2021/04/28 Golang
新手必备Python开发环境搭建教程
2021/05/28 Python
部分武汉产收音机展览
2022/04/07 无线电