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 相关文章推荐
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
May 17 Python
利用numpy+matplotlib绘图的基本操作教程
May 03 Python
Python使用Scrapy爬虫框架全站爬取图片并保存本地的实现代码
Mar 04 Python
Python实现按中文排序的方法示例
Apr 25 Python
python pycurl验证basic和digest认证的方法
May 02 Python
python 日期操作类代码
May 05 Python
pycharm 主题theme设置调整仿sublime的方法
May 23 Python
Django实战之用户认证(初始配置)
Jul 16 Python
Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现
Aug 13 Python
python 根据网易云歌曲的ID 直接下载歌曲的实例
Aug 24 Python
Python代码块及缓存机制原理详解
Dec 13 Python
python使用自定义钉钉机器人的示例代码
Jun 24 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版(2)
2006/10/09 PHP
建立文件交换功能的脚本(二)
2006/10/09 PHP
php4的session功能评述(二)
2006/10/09 PHP
php 信息采集程序代码
2009/03/17 PHP
php excel reader读取excel内容存入数据库实现代码
2012/12/06 PHP
php获取当月最后一天函数分享
2015/02/02 PHP
对于Laravel 5.5核心架构的深入理解
2018/02/22 PHP
基于thinkphp6.0的success、error实现方法
2019/11/05 PHP
javascript 写类方式之一
2009/07/05 Javascript
利用jQuery 实现GridView异步排序、分页的代码
2010/02/06 Javascript
jQuery Clone Bug解决代码
2010/12/22 Javascript
使用phantomjs进行网页抓取的实现代码
2014/09/29 Javascript
JavaScript获取元素尺寸和大小操作总结
2015/02/27 Javascript
使用nodejs开发cli项目实例
2015/06/03 NodeJs
jQuery插件ImageDrawer.js实现动态绘制图片动画(附源码下载)
2016/02/25 Javascript
老生常谈combobox和combotree模糊查询
2017/04/17 Javascript
在node中如何使用 ES6
2017/04/22 Javascript
JavaScript数组_动力节点Java学院整理
2017/06/26 Javascript
javascript+css3开发打气球小游戏完整代码
2017/11/28 Javascript
Vue.js通用应用框架-Nuxt.js的上手教程
2017/12/25 Javascript
如何让Nodejs支持H5 History模式(connect-history-api-fallback源码分析)
2019/05/30 NodeJs
[01:13:18]Secret vs Infamous 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.23
2019/09/05 DOTA
如何利用Boost.Python实现Python C/C++混合编程详解
2018/11/08 Python
Python实现将HTML转成PDF的方法分析
2019/05/04 Python
Python 数据可视化pyecharts的使用详解
2019/06/26 Python
简单了解python的内存管理机制
2019/07/08 Python
python实现处理mysql结果输出方式
2020/04/09 Python
浅析HTML5中header标签的用法
2016/06/24 HTML / CSS
HTML5页面直接调用百度地图API获取当前位置直接导航目的地的实现代码
2018/03/02 HTML / CSS
找到不普通的东西:Bonanza
2016/10/20 全球购物
人事经理岗位职责
2014/04/28 职场文书
2014年巴西世界杯口号
2014/06/05 职场文书
单方离婚协议书范本(2014版)
2014/09/30 职场文书
2015年教师节新闻稿
2015/07/17 职场文书
村官2015年度工作总结
2015/10/14 职场文书
2016教师校本培训心得体会
2016/01/08 职场文书