1,mongodb 3.2版本才有聚合操作,如果你是用的版本低于3.2,请先升级版本。
代码基于 php7 原生驱动,php5或者mongodb library 类库的,请出门从外面关上门,不送。
2,使用的php操作类 请先查看本文的上一章节
3,在上一章节中 我们介绍 Command 命令时候使用了一个例子
统计一个集合下的数据量 类似mysql 的 count
$cmd=["count" => $table,"query" =>$filter];
$model->query('',$cmd,[],'command');
$cmd中 count指定某个集合 query 是对集合进行过滤 $filter和普通查询中的使用方法一样。
4,这个例子也可以使用聚合来实现,实现的基础操作也是基于 manager()->executeCommand
$cmd=[
'aggregate' => $table, /*指定对那个集合进行 聚合操作*/
'pipeline' => [
['$match' => $filter], /*过滤数据 $filter 的具体用法 参照 上一章节的查询*/
['$group' => [
'_id' => '$type', /*指定字段 group分组 这里的 '_id' 不是指代集合中主键,你可以把它理解为语法关键字 $type 才是分组字段 $type可以null 意思就是不按字段分组,把整个表视作一个组*/
'count' => [ '$sum' => 1] /* 这里的 'count' 是自定义的显示字段,和数据库的的列没有直接关系,相当于 mysql里面的 sum(1) as count,sum 是求和,但是结果是行数 */
]]
],
'cursor' => new \stdClass()
$res=$model->query('',$cmd,[],'command');
/*这个 pipeline下的结构体很容易搞错格式 [['$match'=>[]],['$group'=>[]]] 一定要按这个格式,丝毫不能差,否则php一般会报 CommandException: 'pipeline' option must be specified as an array in 类似的错误 */
返回值是一个array数组
Array
(
[0] => stdClass Object
(
[_id] =>
[count] => 273
)
)
这个示例中 ['$sum'=>1] 是聚合操作函数 类似 mysql中 sum() 求和函数,但是mongodb中是没有count()这个计数函数的。
$avg $min $max 这三个也是合法的聚合函数。
5,pipeline 英文原意是管道, 你可以数据就像流水一样,依次从pipeline的每一个子项流过,依次进行处理,
就像整个实例中 数据先经过 ['$match' => $filter] 进行过滤处理,再经过['$group' =>[]]进行分组加工。
mysql中groupby 后有having 对分组后的数据进行再次过滤。mongodb可以基于管道的原理,可以在group后继续用 $match方法进行过滤。
类似的函数还有 $project 和普通查询用法一样,就是控制字段的显示。这个方法可以方法 放在 $match前面也可以方法 $group 的后面。
$cmd=[
"aggregate" => 'user_log_04_19',
"pipeline" =>[
['$project'=>['_id'=>1,'path'=>1,'ip'=>1,'time'=>1]], /*指定只显示四个字段*/
['$match'=>['ip'=>['$regex'=>'^222.']]], /*ip按条件过滤*/
['$group'=>[
'_id'=>'$path',
'count'=>['$sum'=>1],
'ip'=>['$first'=>'$ip'],
'time'=>['$last'=>'$time']
]],
['$match'=>['count'=>['$gt'=>10]]], /*类似mysql中的having,对分组后的数据继续过滤*/
['$project'=>['_id'=>0,'count'=>1,'ip'=>1,'time'=>1]], /*字段path已经聚合,显示成_id 但是需要隐藏*/
['$sort'=>['_id' => -1]], /*排序*/
['$skip'=>0],
['$limit'=>10],
['$count'=>'count'] /*count方法对统计结果集 赋值给count 字段*/
],
'cursor' => new \stdClass()
];
$res=$model->query('',$cmd,[],'command');
这个实例完整的演示了,管道参数传递,多次使用$match数据过滤和$project字段显示隐藏,以及多种聚合操作函数。
更多聚合操作函数以及管道函数
6,distinct 去重复,这个可以用聚合实现,要去重的字段进行聚合后使用管道筛选数据就可以,单独说这个问题,是因为mongodb官方还提供了另一种操作方式。
$cmd=["distinct" => $table,'key'=>$field,"query" =>$filter]; /*key 就是要去重的字段 这个方法实际是上和count一样都是 command命令 */
$model->query('',$cmd,[],'command');
总结 为什么很多人都吐槽 php7 mongodb的原生驱动不好用,因为官方文档太简略,需要程序员自己去摸索实践。我也是经过一个星期的功夫,反复测试总结才有了这三篇干货文章,希望能让让看到的人少走一些弯路。