MongoDB中的数据聚合工具Aggregate和Group
周煦辰 2016-01-16
来说说MongoDB中的数据聚合工具。
Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY。聚合工具可以让开发人员直接使用MongoDB原生的命令操作数据库中的数据,并且按照要求进行聚合。聚合不仅极大提升了开发的效率,更重要的是,原生的工具运行效率比自己写聚合的方法高到不知道哪里去了。
下面简单说一下PHP开发环境下如何使用MongoDB的数据聚合工具 Aggregation Pipleline和Group。其实PHP下的MongoDB使用和原生差不多,无非是语法从JavaScript变成了PHP而已,大致的操作流程是差不多,命令的格式也是非常相像的。基本上只要会看MongoDB的文档,就能通过PHP操作MongoDB了。
Aggregation Pipleline
关于Aggregation,官方文档在这里。我这里就半翻译半扯淡(当然大部分是扯淡)说一下Aggregation Pipleline。
管道的概念
管道在*nix中将上一个命令输出的数据作为下一个命令的参数。MongoDB中的管道操作是可以重复的,基于这个概念,MongoDB中的管道聚合可以有非常实用的玩法,比如对聚合的结果进行排序。
那么,如何使用呢

借用一下官方的图,这里aggregate的命令为:
[
{$match: {status: "A"}},
{$group: {_id: "$cust_id", total: {$sum: "$amount"}}}
]
aggreagte是一个数组,其中包含多个对象(命令),通过遍历Pipleline数组对collection中的数据进行操作。
解释一下例子中的配置项意思。
$match:查询条件
- 经常使用正则表示的人肯定对match不陌生,很明显
$match是配置查询数据时的条件。这里的语法和查询数据库的时候一毛一样,也就不再赘述了,看一下MongoDB的CRUD文档即可。
$group:聚合的配置
_id代表你想聚合的数据的主键,例如上述数据中,你想聚合所有cust_id相同的条目的amount的总和,那_id即被设置为cust_id。_id为必须,但是你可以填写一个空值。total代表你最后想输出的数据之一,这里total是每条结果中amount的总和。$sum是一个聚合的操作符,另外的操作符你可以在官方文档中找到。上图中的命令表示对相同主键(_id)下的amount进行求和。如果你想要计算主键出现的次数,可以把命令写成如下的形式
{$sum: 1}
聚合的过程
看一下图例,所有的数据先经过$match命令,只留下了status为A的数据,接着,对筛选出的数据进行聚合操作,对相同cust_id的数据进行计算amount总和的操作,最后输出结果。
其他管道表达式与操作符
这里说一下$sort操作符。前面说过,利用管道的特性,可以做到对结果进行排序。所以只需要在$group操作之后使用$sort操作即可,这点在报表的制作上十分实用。况且使用MongoDB对结果进行排序也可以尽量优化性能。
Group
MongoDB另一个重要的聚合工具就是Group,所不同的是,Aggregate操作中,传入的Pipleline是一个包含多个对象的数组,每一个对象代表了一个命令。而Group有传入的命令中共有六个参数,其中三个……是JavaScript函数,因此每次查询到匹配的数据,都会被转换为对象传入函数。从运行效率上来说,Group肯定比Aggregate差一大截。但是Group的优势在于灵活,因为配置项可以通过自己编写函数来实现。但是需要注意的是,尽管这样做看起来非常灵活方便,但是一旦函数复杂度过大,将大大影响Group的性能,因此个中取舍还需要自己定夺。
那么,怎么用呢
从我个人来说,用得最多的是key、cond、$reduce、inital这四个命令。
使用上面Aggregation Pipleline中的数据为例。
key:其实和上边说的Aggregation Pipleline中的_id是一样的。假设这里是{cust_id: 1}cond:和上边说的$match是一样的。$reduce:一个函数,对匹配到的数据进行操作,这个放在后面说。initial:初始数据,假设我们这里是{count: 0}。
$reduce:
function(obj, prev) {
prev.count += obj.amount;
}
$reduce的函数(还是匿名的)可以传入两个参数,第一个是被转换为对象的条目,第二个是被实例化的initial对象。
最后的结果和Aggregate操作的一样:
{
retval: [
{
cust_id: "A123",
count: 750
},
{
cust_id: "B212",
count: 200
}
],
count: 3,
keys: 2,
ok: 1
}
那么,PHP里面应该怎么用呢
PHP中的Mongo操作和原生的使用JavaScript操作非常像。例如第一个例子的代码如下:
<?php
$mongo = new MongoClient(DB_CONNECT);
$db = $mongo->db;
$collection = $db->selectCollection('orders');
$pipleline = array(
array(
'$match' => array(
'status' => array(
'$eq' => 'A',
),
),
),
array(
'$group' => array(
'_id' => '$cust_id',
'total' => array(
'$sum' => '$amount',
),
),
),
);
$a = $collection->aggregate($pipleline);
$result = isset($a['result']) ? $a['result'] : array();
第二个例子的代码如下
<?php
$mongo = new MongoClient(DB_CONNECT);
$db = $mongo->db;
$collection = $db->selectCollection('orders');
$keys = array('cust_id' => 1);
$initial = array('count' => 0);
$reduce = 'function(obj, prev) {prev.count += obj.amount;}';
$cond = array('condition' => array('status' => 'A'));
$g = $collection->group($keys, $initial, $reduce, $cond);
$retval = isset($g['retval']) ? $g['retval'] : array();
其他的功能,需要自己多参考PHP官方文档和Mongo的文档进行尝试了。
MongoDB中的数据聚合工具Aggregate和Group的更多相关文章
- MongoDB中聚合工具Aggregate等的介绍与使用
Aggregate是MongoDB提供的众多工具中的比较重要的一个,类似于SQL语句中的GROUP BY.聚合工具可以让开发人员直接使用MongoDB原生的命令操作数据库中的数据,并且按照要求进行聚合 ...
- 使用highcharts显示mongodb中的数据
1.mongodb数据表相关 # 显示数据库 show dbs # 数据库 use ceshi # 显示表 show tables # 创建集合 db.createCollection('infoB' ...
- MongoDB中导入数据命令的使用(mongoimport)
MongoDB中导入数据命令的使用(mongoimport) 制作人:全心全意 语法: mongoimport <options> <file> 介绍: 该命令可以将CSV,T ...
- 用java在客户端读取mongodb中的数据并发送至服务器
使用Java自带的socket端口来实现,程序如下: Client.java package com.cn.gao; import java.net.*; import java.io.*; impo ...
- PHP 从 MongoDb 中查询数据怎么样实现
一.软件环境(版本非必须) php v5.6 扩展:MongoDB nginx v1.11 mongodb v3.2 note: 必须安装MongoDB扩展 二.连接 $client = new Mo ...
- 解决Spring中使用Example无法查询到Mongodb中的数据问题
1 问题描述 在Spring Boot中使用Mongodb中的Example查询数据时查询不到,示例代码如下: ExampleMatcher matcher = ExampleMatcher.matc ...
- 2.(group by)如何让分组后,每组中的数据按时间倒序排列(group by和 order by的分组按排列)
比如说有表devicedata: 问题: 现在我想将devicedata这个表中的数据,先按device_id这个字段分组,然后每组中的数据按时间字段ts从大到小的排列, 如何解决呢? 错误的sql: ...
- 使用C#对MongoDB中的数据进行查询,改动等操作
首先,使用的是官方提供的C#訪问组件https://github.com/mongodb/mongo-csharp-driver 然后.编译后引用MongoDB.Bson.dll及MongoDB.Dr ...
- Java对MongoDB中的数据查询处理
Java语言标准的数据库时MySQL,但是有些时候也会用到MongoDB,这次Boss交代处理MongoDB,所以讲代码以及思路记录下了 摸索的过程,才发现软件的适用还是很重要的啊!!! 我连接的Mo ...
随机推荐
- C++程序风格的思考
转载自:http://www.cppblog.com/weiym/archive/2013/04/27/199781.html 发现厚积薄发中有很多值得学习的东西 故引用之: 最近有机会看号称是公司最 ...
- TA-Lib中文文档(一):快速开始
TA-Lib 简介: 这是一个Python 金融指数处理库TA-LIB,他是基于 Cython 而不是 SWIG. TA-Lib is widely used by trading software ...
- supervisord部署
https://blog.csdn.net/vbaspdelphi/article/details/54091095https://blog.csdn.net/shudaqi2010/article/ ...
- matplotlib常见绘图基础代码小结:折线图、散点图、条形图、直方图、饼图
一.折线图 二.散点图 三.条形图 四.直方图 五.饼图 一.折线图折线图用于显示随时间或有序类别的变化趋势 from matplotlib import pyplot as plt x = rang ...
- POJ1995:Raising Modulo Numbers(快速幂取余)
题目:http://poj.org/problem?id=1995 题目解析:求(A1B1+A2B2+ ... +AHBH)mod M. 大水题. #include <iostream> ...
- log4j2动态修改日志级别及拓展性使用
一.供参考的完整日志配置 <?xml version="1.0" encoding="UTF-8"?> <!-- 配置LoggerConfig ...
- python学习之路-day10
一.什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程. 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程. 车间负责把资源 ...
- android中代码操作外部SD卡出错:W/System.err(1595): Caused by: libcore.io.ErrnoException: open failed: EACCES (Permission denied)
AndroidManifest.xml 中加上: <uses-permission android:name="android.permission.WRITE_EXTERNAL_ST ...
- VS2010/MFC编程入门之二十(常用控件:静态文本框)
上一节鸡啄米讲了颜色对话框之后,关于对话框的使用和各种通用对话框的介绍就到此为止了.从本节开始鸡啄米将讲解各种常用控件的用法.常用控件主要包括:静态文本框.编辑框.单选按钮.复选框.分组框.列表框.组 ...
- 推荐一个js脚本的字体拟合模型
推荐一个js脚本的字体拟合模型 http://r3mi.github.io/poly2tri.js/ 推荐一个js脚本的字体拟合模型 http://r3mi.github.io/poly2tri. ...