来讲说MongoDB中的数据聚合工具。javascript
Aggregate是MongoDB提供的众多工具中的比较重要的一个,相似于SQL语句中的GROUP BY
。聚合工具可让开发人员直接使用MongoDB原生的命令操做数据库中的数据,而且按照要求进行聚合。聚合不只极大提高了开发的效率,更重要的是,原生的工具运行效率比本身写聚合的方法高到不知道哪里去了。
下面简单说一下PHP开发环境下如何使用MongoDB的数据聚合工具 Aggregation Pipleline和Group。其实PHP下的MongoDB使用和原生差很少,无非是语法从JavaScript变成了PHP而已,大体的操做流程是差很少,命令的格式也是很是相像的。基本上只要会看MongoDB的文档,就能经过PHP操做MongoDB了。php
关于Aggregation,官方文档在这里。我这里就半翻译半扯淡(固然大部分是扯淡)说一下Aggregation Pipleline。java
管道在*nix中将上一个命令输出的数据做为下一个命令的参数。MongoDB中的管道操做是能够重复的,基于这个概念,MongoDB中的管道聚合能够有很是实用的玩法,好比对聚合的结果进行排序。mongodb
借用一下官方的图,这里aggregate的命令为:数据库
[ {$match: {status: "A"}}, {$group: {_id: "$cust_id", total: {$sum: "$amount"}}} ]
aggreagte是一个数组,其中包含多个对象(命令),经过遍历Pipleline数组对collection中的数据进行操做。
解释一下例子中的配置项意思。数组
$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对结果进行排序也能够尽可能优化性能。
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中的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的文档进行尝试了。