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实现八大排序算法(2)
Sep 14 Python
Python实现简单的语音识别系统
Dec 13 Python
Python3正则匹配re.split,re.finditer及re.findall函数用法详解
Jun 11 Python
python针对不定分隔符切割提取字符串的方法
Oct 26 Python
python 多进程共享全局变量之Manager()详解
Aug 15 Python
基于python进行抽样分布描述及实践详解
Sep 02 Python
解决python 找不到module的问题
Feb 12 Python
python GUI库图形界面开发之PyQt5信号与槽基本操作
Feb 25 Python
解决pycharm下pyuic工具使用的问题
Apr 08 Python
通过实例了解python__slots__使用方法
Sep 14 Python
Python获取指定网段正在使用的IP
Dec 14 Python
Python命令行参数argv和argparse该如何使用
Feb 08 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数组键名技巧小结
2015/02/17 PHP
PHP 记录访客的浏览信息方法
2018/01/29 PHP
用正则xmlHttp实现的偷(转)
2007/01/22 Javascript
如何让页面在打开时自动刷新一次让图片全部显示
2012/12/17 Javascript
jquery动态增加text元素以及删除文本内容实例代码
2013/07/01 Javascript
JavaScript对象数组的排序处理方法
2015/10/21 Javascript
阿里巴巴技术文章分享 Javascript继承机制的实现
2016/01/14 Javascript
浅谈JavaScript for循环 闭包
2016/06/22 Javascript
ionic2打包android时gradle无法下载的解决方法
2017/04/05 Javascript
angular2 ng build部署后base文件路径问题详细解答
2017/07/15 Javascript
jQuery实现checkbox即点即改批量删除及中间遇到的坑
2017/11/11 jQuery
nodejs前端模板引擎swig入门详解
2018/05/15 NodeJs
vue3.0 CLI - 2.2 - 组件 home.vue 的初步改造
2018/09/14 Javascript
如何基于vue-cli3.0构建功能完善的移动端架子
2019/04/24 Javascript
Vue发布项目实例讲解
2019/07/17 Javascript
利用 JavaScript 实现并发控制的示例代码
2020/12/31 Javascript
python字典序问题实例
2014/09/26 Python
为Python程序添加图形化界面的教程
2015/04/29 Python
Python 的类、继承和多态详解
2017/07/16 Python
TensorFlow saver指定变量的存取
2018/03/10 Python
python3使用SMTP发送简单文本邮件
2018/06/19 Python
解决python3 Pycharm上连接数据库时报错的问题
2018/12/03 Python
python使用pymongo操作mongo的完整步骤
2019/04/13 Python
Apache部署Django项目图文详解
2019/07/30 Python
浅析Python迭代器的高级用法
2020/07/16 Python
利用CSS3实现单选框动画特效示例代码
2016/09/26 HTML / CSS
Woolworth官网:澳洲第一大超市
2017/06/25 全球购物
解释i节点在文件系统中的作用
2013/11/26 面试题
实习报告评语
2014/04/26 职场文书
新法人代表任命书
2014/06/06 职场文书
领导班子奢靡之风查摆问题及整改措施
2014/09/27 职场文书
公司员工安全协议书
2014/11/21 职场文书
表彰大会新闻稿
2015/07/17 职场文书
教师个人教学反思
2016/02/23 职场文书
Python实现文本文件拆分写入到多个文本文件的方法
2021/04/18 Python
Python实现制作销售数据可视化看板详解
2021/11/27 Python