MongoDB3.2 之 aggregate的管道符详述

来源:互联网 发布:javascript 写法 编辑:程序博客网 时间:2024/06/01 10:02

众所周知,aggregate是mongodb非常强大的工具之一,之所以强大是因为它可以像乐高一样随意摆放各种组件(当然还是要遵守一定规则的)
下面我们就对aggregate的十三金钗进行一一解释;
汇总:
        $match:  匹配查询条件,针对的是源集合,可多次使用;
        $limit: 限制输出的结果集 ;
        $lookup: left join其他集合,且两个集合必须在一个库下 ;
        $group: 类似于关系型数据库的group by,其后也可以加上诸多操作,比如$sum,$max,$min
        $unwind: 分裂数组,重组数据 ;
        $project: 字段重命名,字段做运算,合并,选择性的增加或删除字段;
        $sort: 排序, 类似 order by
        $skip: 省略某些行,类似find()后面的skip()
        $redact: document内容的判断和"修剪”;
        $sample: 随机选取指定数量的document;
        $out: 将结果集输出到指定collection中;
        $indexStats: 统计collection中的索引使用信息;
        $geoNear: 根据位置信息查找最近和最远的点


数据集合

下面就简单介绍一下各个组件的使用方法:
1、$project:
     遍历文档的指定字段到下一个stage(阶段);
     意思就是说可以过滤掉某些字段(包括过滤掉_id)、可以重命名字段、添加新的字段,重置字段的值
     语法:
{ $project: { <specifications> } }     
     
<specifications>的选项
描述
<field>: <1 or true>
执行显示哪些字段
_id: <0 or false>
过滤掉_id字段
<field>: <expression>
添加新字段或者重置字段的值
     举例:
     
2、$match:
     查询需要的数据给到下一个stage;
     如果放到aggregate开端的话,可以利用上索引,与find()中的query语法一致
     语法:
{ $match: { <query> } }     ---query中写什么呢?就是在find()中写的东东
     举例:
        
3、$limit:
     其实就是做一个行数的限制,类似top 10 *
     语法:
{ $limit: <positive integer> }
     举例:
       
4、$lookup:
      left join同一库下的另一集合去过滤数据,
语法:
 $lookup:    {      from: <collection to join>,     ---left join后的那个集合名称      localField: <field from the input documents>,     ---用于链接的源集合的字段名      foreignField: <field from the documents of the "from" collection>,     ---left join后的集合的链接字段      as: <output array field>     ---从另一集合链接过来的数据会存放在一个数组中,这是写该数组的名称    }}

注:如果你想要使用源集合中的数组的某个元素作为链接字段,那么你就需要考虑使用$unwind了,什么?你还不懂$unwind是什么?那就继续向下看吧
     举例:
     
5、$unwind:
     分裂数组,重组数据(document)
语法:
{  $unwind:    {      path: <field path>,     ---你想要分裂的数组名称      includeArrayIndex: <string>,     ---新增加一个字段用于描述数组分裂后各个元素在原数组中的位置,此处写新增字段的名(可选参数)      preserveNullAndEmptyArrays: <boolean>     ---默认情况下对没有此数组的行不予显示,但如果想显示则设置为true,默认是false(可选参数)    }}
     举例说明:
数据结构如下
        
普通分裂之后:
       
如果还想加上后面那俩货(参数),那么:
      
6、$group
     将字段进行分组,并执行相应的操作,比如sum,max,min,但其不能排序结果集
语法:
{ $group: { _id: <expression>, <field1>: { <accumulator1> : <expression1> }, ... } }
expression1有很多选项:
$sum     
$avg
$first
$last
$max
$min
$push
$addToSet
$stdDevPop
$stdDevSamp
可能看语法有点迷糊哦,直接上实例
数据结构:
    
分组:
      
分组并计算:
(注:count字段后面的操作可以是其他,比如max,min,push等等)
      

多字段分组并计算
(注:class_id,age,count的这些字段名都可以随便写哦,不要拘泥于制度)
    

7、$redact:
     这是一个非常难以理解的管道符,我算是服了,整了好久也不是太明白啥意思
     根据字段所处的document结构的级别,对文档进行适合的“修剪”,它通常和判断语句if...else结合使用,可选值有3个:
     1)$$DESCEND:包含当前document级别的所有fields。当前级别字段的内嵌文档将会被继续检测。

     2)$$PRUNE:不包含当前文档或者内嵌文档级别的所有字段,不会继续检测此级别的其他字段,即使这些字段的内嵌文档持有相同的访问级别。

     3)$$KEEP:包含当前文档或内嵌文档级别的所有字段,不再继续检测此级别的其他字段,即使这些字段的内嵌文档中持有不同的访问级别。
     其实说的啥意思呢?就是某个字段符合$cond中的条件后如何处理后续字段,
     ① $$DESCEND: 符合条件后其他字段也都显示出来,并且对那些数据类型是数组或者内嵌文档的字段继续进行一样的if判断一样的处理
     ② $$PRUNE: 对符合条件的文档中所有字段全部不显示,更不会深入数组或内嵌文档汇总进行if检测
     ③$$KEEP:对符合条件的文档中同一级别的字段显示出来,但不会深入到数组或者内嵌文档的字段中进行if...else判断
举例:
     集合数据结构
     
     对age字段进行条件判断
db.t6.aggregate([    {$redact:{        $cond:{          ---固定格式,无需理解            if:{$gte:["$age",20]},     ---判断挑那,判断字段age>20的情况            then:"$$DESCEND",          ---如果成立,则显示同级别的所有字段,并继续深入检测            else:"$$PRUNE"               ---如果不成立,则同级别的所有字段全都不显示,且停止再深入检测        }    }}    ])

      
8、$sample:
     从上一个stage中随机选取指定数量的document
     语法:
{ $sample: { size: <positive integer> } }          ---size后面直接指定数字,代表你想选取的随机文档数量
   

9、$out:
     将aggregate的聚合结果集输出到指定collection中存起来,(注:$out必须放到管道符的最后一个)
     其实在我看来类似于 临时表的形式,不过咱们这个生成的是一个真实的实体集合,不会随着session的结束而删除
语法:
{ $out: "<output-collection>" }
举例:
db.t1.aggregate([
        {$sample:{size:2}},
        {$out:"random_test"}
    ])
       
10、$sort
     将结果集以某字段排序,只是排序不会改变任何document
语法:
{ $sort: { <field1>: <sort order>, <field2>: <sort order> ... } }     ---可以指定多个字段,1代表升序 -1代表降序,类似 ordery by field1 ASC ,field2 DESC
举例:
    
限制:默认,$sort阶段有100M内存的使用限制,查过此限制则会报错
        
如果想处理超过100M的数据集,则需要考虑使用allowDiskUse选项,执行命令后会在dbpath的路径下产生一个_tmp的文件夹,用于临时存放sort的数据
     
11、$indexStats
     查询一个collection中每一个index的统计信息
语法:
{ $indexStats: { } }               ---写一个空{}就可以了
举例:
       
{    "name" : "cdate_-1",          ---索引名    "key" : {        "cdate" : -1               ---索引使用的具体字段    },    "host" : "hostname111:27027",          ---mongod进程所在的主机名    "accesses" : {        "ops" : NumberLong("4"),          ---索引被访问的次数,        "since" : ISODate("2017-07-07T02:36:58.440Z")          ---mongod开始收集index统计信息的时间    }},
注:ops 表示访问次数,但是不包括$match和mapReduce操作的访问,也不包括内部操作比如TTL索引的内部每60秒自动删除过期数据的索引访问;
     mongod重启,或者索引被删除重建后,索引的统计信息将被重置
12、$skip
     省略掉一定数量的document,其实这个命令很是简单,功能作用也都好理解,我就不过于分析解释了,相信大家都是聪明人,哈哈...
语法:
{ $skip: <positive integer> }     ---skip后面写个整数就可以了

13、$geoNear
     此命令主要是用于地理位置查找分析,查找距离某个位置最近和最远的点,这个目前我们也用不上,看着还挺复杂,所以偶就先不研究了,后续补充上,


好的,开始下一话题,母猪的产后护理










原创粉丝点击