pymongo中聚合查询的使用方法


Posted in Python onMarch 22, 2019

前言

在使用mongo数据库时,简单的查询基本上可以满足大多数的业务场景,但是试想一下,如果要统计某一荐在指定的数据中出现了多少次该怎么查询呢?笨的方法是使用find 将数据查询出来,再使用count() 方法进行数据统计,这个场景还好,但是如果要求其中某个字段的和呢?是不是就非得遍历出相应的数据然后再进行求和运算呢?

在mysql中我们经常会用到count、group by 等查询,在mongodb中我们也可以使用聚合查询。

假设有这样的一组数据

pymongo中聚合查询的使用方法
价格

里面记录了每种水果的价格,现在我要统计一下,各种水果在这张表中出现的次数,如果不用聚合查询的话,思路应该是这样,先把表中所有的数据都取出来,然后初始化一个字典,然后再遍历每一行的数据,获取它的fName ,然后再更新字典中的计数,这种方法的时间复杂度是O(N)的,如果数据量很大的话不是很好,下面来看一下使用聚合是怎么查询的。

聚合查询使用的是aggregate函数,它的参数是 pipeline 管道,管道的概念是用于将当前命令的输出结果作为下一个命令的参数,管道是有顺序的,比如通过第一个管道操作以后没有符合的数据那么之后的管道操作也就不会有输入,所以一定得要注意管道操作的顺序。由于对于上述问题,我们要的是所的数据统计,所以这里就不需要$match了

from pymongo import MongoClient

client = MongoClient(host=['%s:%s'%(mongoDBhost,mongoDBport)])
G_mongo = client[mongoDBname]['FruitPrice']

pipeline = [
 {'$group': {'_id': "$fName", 'count': {'$sum': 1}}},
 ]
for i in G_mongo['test'].aggregate(pipeline):
 print i

数据大家可以自已构造,这里主要是看aggregate的用法。
得到的结果是

{u'count': 8, u'_id': u'banana'}
{u'count': 9, u'_id': u'pear'}
{u'count': 14, u'_id': u'apple'}

可以看到,一步操作就可以得到相应的统计了。

如果想要获取价格在50以上的各种统计呢?

这时有pipeline应该再$group 之前加上$match 操作

pipeline = [
 {'$match':{'price':{'$gte':50}}},
 {'$group': {'_id': "$fName", 'count': {'$sum': 1}}},
 ]

一定要注意顺序

$match里的条件其实就和使用find函数里是一样的。

下面重点来说说$group操作,group意为分组,指数据根据哪个字段进行分组,上面使用的{'$group': {'_id': "$fName", 'count': {'$sum': 1},_id为所要分的组,这里是以fName字段分的,后面的'count': {'$sum': 1},这里的$sum就是求和的意思,后面的值是1,也就是说每出现一次就加1,这样就能达到计数的目的了,如果要计算价格 price 的和,那么这里就应该写成这样

{'$group': {'_id': "$fName", 'count': {'$sum': '$price'}}}

注意这里的字段要有$ 的,如果我想要求价格的平均值呢?也就是先要求出价格的总数,再除以商品的个数,但是这里有一个$avg 操作

pipeline = [
 {'$match':{'price':{'$gte':50}}},
 {'$group': {'_id': "$fName", 'avg': {'$avg': '$price'}}},
 ]

得到的结果

{u'_id': u'banana', u'avg': 66.200000000000003}
{u'_id': u'pear', u'avg': 77.0}
{u'_id': u'apple', u'avg': 74.0}

类似于$ave的操作还有很多,比较常用的是$min(求最小值),$max(求最大值)

pipeline = [
 {'$match':{'price':{'$gte':50}}},
 {'$group': {'_id': "$fName",
  'count':{'$sum':1},
  'priceAll':{'$sum':'$price'},
  'avg': {'$avg': '$price'},
  'min': {'$min':'$price'},
  'max': {'$max':'$price'}
  }
 },
 ]
for i in G_mongo['test'].aggregate(pipeline):
 print i

所有支持的操作可以参考官方文档:group 支持的操作

以哪个字段进行分组时必须使用_id。

接下来看一下多键分组。

以上在使用group 进行分组查询的时候,用到的_id都是单一字段,比如我的数据库中有如下数据

pymongo中聚合查询的使用方法
带用户的数据

带有一个user 字段了,那如果我要根据user和fName进行分组该如何操作呢?
这里可以传一个字典进去

pipeline = [
 {'$match':{'price':{'$gte':50}}},
 {'$group': {'_id': {'fName':'$fName','user':'$user'},
  'count':{'$sum':1},
  'priceAll':{'$sum':'$price'},
  'avg': {'$avg': '$price'},
  'min': {'$min':'$price'},
  'max': {'$max':'$price'}
  }
 },
 ]
for i in G_mongo['test2'].aggregate(pipeline):
 print i

得到的结果如下:

{u'count': 1, u'avg': 93.0, u'min': 93, u'max': 93, u'_id': {u'user': u'fanjieying', u'fName': u'pear'}, u'priceAll': 93}
{u'count': 2, u'avg': 88.0, u'min': 87, u'max': 89, u'_id': {u'user': u'yangyanxing', u'fName': u'banana'}, u'priceAll': 176}
{u'count': 2, u'avg': 70.0, u'min': 69, u'max': 71, u'_id': {u'user': u'yangyanxing', u'fName': u'pear'}, u'priceAll': 140}
{u'count': 2, u'avg': 65.5, u'min': 58, u'max': 73, u'_id': {u'user': u'fanjieying', u'fName': u'banana'}, u'priceAll': 131}
{u'count': 3, u'avg': 92.333333333333329, u'min': 86, u'max': 97, u'_id': {u'user': u'fantuan', u'fName': u'banana'}, u'priceAll': 277}
{u'count': 2, u'avg': 78.5, u'min': 73, u'max': 84, u'_id': {u'user': u'yangyanxing', u'fName': u'apple'}, u'priceAll': 157}
{u'count': 3, u'avg': 56.666666666666664, u'min': 51, u'max': 60, u'_id': {u'user': u'fantuan', u'fName': u'pear'}, u'priceAll': 170}
{u'count': 2, u'avg': 81.5, u'min': 73, u'max': 90, u'_id': {u'user': u'fanjieying', u'fName': u'apple'}, u'priceAll': 163}
{u'count': 2, u'avg': 69.5, u'min': 53, u'max': 86, u'_id': {u'user': u'fantuan', u'fName': u'apple'}, u'priceAll': 139}

这里的结果显示出每个用户买了哪个商品,一共花了多少钱,最大最小平均值等都可以一次性的展示了,如果要是使用for循环自已遍历的话这种时间复杂度相当高。

这里只是简单的说了下$group和$match 的用法,聚合查询支持很多种操作(称为stages),可以通官方文档进行查看
pymongo 中pipeline中的stages

参考文章

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Python 相关文章推荐
Python ValueError: invalid literal for int() with base 10 实用解决方法
Jun 21 Python
编写Python脚本抓取网络小说来制作自己的阅读器
Aug 20 Python
详解python 拆包可迭代数据如tuple, list
Dec 29 Python
python保存文件方法小结
Jul 27 Python
在win10和linux上分别安装Python虚拟环境的方法步骤
May 09 Python
python web框架Flask实现图形验证码及验证码的动态刷新实例
Oct 14 Python
python中with语句结合上下文管理器操作详解
Dec 19 Python
Pandas时间序列:重采样及频率转换方式
Dec 26 Python
关于tensorflow的几种参数初始化方法小结
Jan 04 Python
解决pytorch DataLoader num_workers出现的问题
Jan 14 Python
深度学习小工程练习之垃圾分类详解
Apr 14 Python
Python超简单容易上手的画图工具库推荐
May 10 Python
OpenCV HSV颜色识别及HSV基本颜色分量范围
Mar 22 #Python
基于OpenCV python3实现证件照换背景的方法
Mar 22 #Python
详解Python给照片换底色(蓝底换红底)
Mar 22 #Python
详解python-图像处理(映射变换)
Mar 22 #Python
python中如何使用分步式进程计算详解
Mar 22 #Python
浅谈Python基础—判断和循环
Mar 22 #Python
浅谈python常用程序算法
Mar 22 #Python
You might like
PHP4实际应用经验篇(8)
2006/10/09 PHP
浅析ThinkPHP的模板输出功能
2014/07/01 PHP
thinkPHP线上自动加载异常与修复方法实例分析
2016/12/01 PHP
基于JavaScript 下namespace 功能的简单分析
2013/07/05 Javascript
JavaScript制作简单的日历效果
2016/03/10 Javascript
node.js express安装及示例网站搭建方法(分享)
2016/08/22 Javascript
jQuery中JSONP的两种实现方式详解
2016/09/26 Javascript
微信小程序 闭包写法详细介绍
2016/12/14 Javascript
js获取地址栏参数的两种方法
2017/06/27 Javascript
详解vue.js+UEditor集成 [前后端分离项目]
2017/07/07 Javascript
js封装成插件_Canvas统计图插件编写实例
2017/09/12 Javascript
微信小程序实现的自定义分享功能示例
2019/02/12 Javascript
微信小程序 下拉刷新及上拉加载原理解析
2019/11/06 Javascript
layui前端时间戳转化实例
2019/11/15 Javascript
[40:55]Liquid vs LGD 2018国际邀请赛小组赛BO2 第二场 8.16
2018/08/17 DOTA
python实现的简单猜数字游戏
2015/04/04 Python
python单例模式获取IP代理的方法详解
2018/09/13 Python
从训练好的tensorflow模型中打印训练变量实例
2020/01/20 Python
Python接口自动化判断元素原理解析
2020/02/24 Python
基于Python数据结构之递归与回溯搜索
2020/02/26 Python
利用Python实现朋友圈中的九宫格图片效果
2020/09/03 Python
深入理解Python变量的数据类型和存储
2021/02/01 Python
Python中Qslider控件实操详解
2021/02/20 Python
MVMT手表官方网站:时尚又实惠的高品质手表
2016/12/04 全球购物
纽约州一群才华横溢的金匠制作而成:Hearth Jewelry
2019/03/22 全球购物
Kusmi茶美国官网:优质散叶茶和茶包
2019/10/13 全球购物
NULL是什么,它是怎么定义的
2015/05/09 面试题
计算机专业个人求职自荐信
2013/09/21 职场文书
网络事业创业计划书范文
2014/01/09 职场文书
无房证明范本
2014/09/17 职场文书
销售人才自我评价范文
2014/09/27 职场文书
2014乡党委副书记党建工作汇报材料
2014/11/02 职场文书
二年级上册数学教学计划
2015/01/20 职场文书
暗恋桃花源观后感
2015/06/12 职场文书
2019求职信:应届生求职信范文
2019/04/24 职场文书
vue 实现弹窗关闭后刷新效果
2022/04/08 Vue.js