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 02 Python
Python中使用PyHook监听鼠标和键盘事件实例
Jul 18 Python
Python操作列表之List.insert()方法的使用
May 20 Python
Python实现新浪博客备份的方法
Apr 27 Python
使用python实现个性化词云的方法
Jun 16 Python
Python代码实现KNN算法
Dec 20 Python
python 按照固定长度分割字符串的方法小结
Apr 30 Python
pytorch 数据集图片显示方法
Jul 26 Python
用Python编写一个简单的CS架构后门的方法
Nov 20 Python
如何使用pandas读取txt文件中指定的列(有无标题)
Mar 05 Python
Python同时迭代多个序列的方法
Jul 28 Python
Python 3.9的到来到底是意味着什么
Oct 14 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的FTP学习(二)[转自奥索]
2006/10/09 PHP
多重?l件?合查?(一)
2006/10/09 PHP
关于PHP5 Session生命周期介绍
2010/03/02 PHP
php 无法加载mysql的module的时候的配置的解决方案引发的思考
2012/01/27 PHP
php提示无法加载或mcrypt没有找到 PHP 扩展 mbstring解决办法
2012/03/27 PHP
在PHP程序中使用Rust扩展的方法
2015/07/03 PHP
js中cookie的使用详细分析
2008/05/28 Javascript
禁止JQuery中的load方法装载IE缓存中文件的方法
2009/09/11 Javascript
判断目标是否是window,document,和拥有tagName的Element的代码
2010/05/31 Javascript
JavaScript中的异常捕捉介绍
2014/12/31 Javascript
AngularJS基础知识笔记之表格
2015/05/10 Javascript
浅析jQuery Ajax请求参数和返回数据的处理
2016/02/24 Javascript
JS读取XML文件数据并以table形式显示数据的方法(兼容IE与火狐)
2016/06/02 Javascript
微信小程序 wxapp内容组件 icon详细介绍
2016/10/31 Javascript
网页挂马方式整理及详细介绍
2016/11/03 Javascript
高性能的javascript之加载顺序与执行原理篇
2018/01/14 Javascript
CSS3 动画卡顿性能优化的完美解决方案
2018/09/20 Javascript
原生js实现可兼容PC和移动端的拖动滑块功能详解【测试可用】
2019/08/15 Javascript
[32:56]完美世界DOTA2联赛PWL S3 Rebirth vs CPG 第二场 12.11
2020/12/16 DOTA
Python version 2.7 required, which was not found in the registry
2014/08/26 Python
跟老齐学Python之Python文档
2014/10/10 Python
Python中实现对Timestamp和Datetime及UTC时间之间的转换
2015/04/08 Python
python dataframe 输出结果整行显示的方法
2018/06/14 Python
用python代码将tiff图片存储到jpg的方法
2018/12/04 Python
Python 处理图片像素点的实例
2019/01/08 Python
PyCharm 专业版安装图文教程
2020/02/20 Python
pytorch查看通道数 维数 尺寸大小方式
2020/05/26 Python
15个应该掌握的Jupyter Notebook使用技巧(小结)
2020/09/23 Python
Python __slots__的使用方法
2020/11/15 Python
学生干部学习的自我评价
2014/02/18 职场文书
黄金搭档广告词
2014/03/21 职场文书
商务代表岗位职责
2015/02/15 职场文书
Go各时间字符串使用解析
2021/04/02 Golang
浅谈Python实现opencv之图片色素的数值运算和逻辑运算
2021/06/23 Python
javascript对象3个属性特征
2021/11/17 Javascript
Python selenium绕过webdriver监测执行javascript
2022/04/12 Python