pymongo中group by的操作方法教程
作者:lionets 发布时间:2021-03-23 05:44:40
前言
使用 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 默认返回浮点数。
来源:https://my.oschina.net/lionets/blog/727188
猜你喜欢
- 大家在使用python的过程中,应该在敲代码的时候经常遇到str内置函数,为了防止大家搞混,本文整理归纳了str内置函数。1字符串查找类:f
- 官方地址:gin-gonic.com/docs/安装与简单测试下载并安装Gin包,并导入引用$ go get -u github.com/g
- 一.主键:1.1)主键字段定义:在数据库表中,如果有一组字段能够唯一确定一条记录,则可以把它们设计成表的主键字段。例子:如果要创
- 1 什么是嵌套循环所谓嵌套循环就是一个外循环的主体部分是一个内循环。内循环或外循环可以是任何类型,例如 while 循环或 for 循环。
- replace方法的语法是:stringObj.replace(rgExp, replaceText) 其中stringObj是字符串(st
- 功能:返回字符、二进制、文本或图像表达式的一部分语法:SUBSTRING ( expression, start, length )&nbs
- 本文实例讲述了javascript insertAfter()定义与用法。分享给大家供大家参考,具体如下:HTML部分:<div id
- 一、Tesseract简介Tesseract是一个OCR库(OCR是英文Optical Character Recognition的缩写),
- 序本文主要研究一下golang的deferdeferreturn先赋值(对于命名返回值),然后执行defer,最后函数返回defer函数调用
- 数据结构Redis有五种基础数据结构,分别为:1、string(字符串)2、list(列表)3、hash(字典)4、set(集合)5、zse
- 前言我们前面对matplotlib模块底层结构学习,对其pyplot类(脚本层)类提供的绘制折线图、柱状图、饼图、直方图等统计图表的相关方法
- 我们自己鼓捣mysql时,总免不了会遇到这个问题:插入中文字符出现乱码,虽然这是运维先给配好的环境,但是在自己机子上玩的时候咧,
- HTML表单是网站交互性的经典方式。 本章将介绍如何用Django对用户提交的表单数据进行处理。一、HTTP 请求HTTP协议以"
- 如果用户查询时,使用Order BY排序语句指定按员工编号来排序,那么排序后产生的所有记录就是临时数据。对于这些临时数据,Oracle数据库
- Javascript中标签(label)是一个标识符。标签可以与变量重名,它是一个独立的语法元素(既不是变量,也不是类型),其作用是标识”标
- 简述队列一直都是工程化开发中经常使用的数据类型,本篇文章主要介绍一下python queue的使用,会边调试代码,边说明方法内容。环境pyt
- 很多现代的浏览器在地址栏的右边有个搜索框,默认的安装有 Google 搜索等。如下图所示:其实这是 OpenSearch 的一个应用,只要编
- 父传子:1、 在父组件的子组件标签上通过 :传递到子组件的数据名="需要传递的数据"在这里为了大家区分我将父组件中的数据
- 在做web应用的自动化测试时,定位元素是必不可少的,这个过程经常会碰到定位不到元素的情况(报selenium.common.exceptio
- 导语哈喽!大家好,我是栗子,感谢大家的支持!新的一天,新气象,程序猿们的日常开始敲敲敲,改改改——今