zoukankan      html  css  js  c++  java
  • 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中的管道聚合可以有非常实用的玩法,比如对聚合的结果进行排序

    那么,如何使用呢

    img

    借用一下官方的图,这里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的性能,因此个中取舍还需要自己定夺。

    那么,怎么用呢

    从我个人来说,用得最多的是keycond$reduceinital这四个命令。

    使用上面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的文档进行尝试了。

  • 相关阅读:
    第四周查漏补缺20165307
    第四周作业 20165307
    第三周作业 20165307
    20165307 第一次测试总结
    20165307 预备作业3 Linux安装及学习
    20165307 学习基础和C语言基础调查
    20165307 我期望的师生关系
    第十周课下补做
    20165336 2016-2017-2 《Java程序设计》第9周学习总结
    20165336 实验三 敏捷开发与XP实践
  • 原文地址:https://www.cnblogs.com/zhouxuchen/p/5136446.html
Copyright © 2011-2022 走看看