MongoDB 4.0.10 聚合

  • db.<collection>.group(document):首先根据cond查询条件筛选符合条件的数据,然后按照key分组属性把数据分成不同组,每一组都经过initial进行变量初始化,在经过reduce函数进行计算,其中curr参数代表该组的一个文档,result参数在最后的时候返回,统计完该组之后调用finalize函数
  • group方法的不足之处:需要手写聚合函数的业务逻辑,且不支持分片计算,无法分布式计算
  • 示例在SQL_DB中Learn09.js
 1 db.<collection>.group(document)
 2 // document指定是
 3 {
 4     key:{key1:1, key2:1},                  // 分组属性
 5     keyf:{ },                              // 可选,用于代替参数key,可以不指定其属性为分组字段的对象,而是指定一个函数,该函数返回一个用于分组的key对象
 6     cond:{ },                              // 可选,查询条件
 7     reduce:function(curr, result){ },      // 每一组数据执行的聚合函数,curr代表该组的一个文档,result代表该组的一个聚合结果
 8     initial:{},                            // 进入每组之前进行变量参数初始化
 9     finalize:function(){ }                 // 可选,统计完一组后的回调函数
10 }
  • db.<collection>.aggregate(AGGREGATE_OPERATION),V2.2加入:这是MongoDB的聚合管道,将MongoDB文档在一个管道处理完毕之后将结果传递给下一个管道处理,管道操作是可以重复的
  • 示例在SQL_DB中Learn10.js
 1 $project //select 修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档
 2 $match   //where/having 用于过滤数据,只输出符合条件的文档;$match使用MongoDB的标准查询操作
 3 $limit   //limit 用来限制MongoDB聚合管道返回的文档数
 4 $skip    // 在聚合管道中跳过指定数量的文档,并返回余下的文档
 5 $unwind  // 将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值
 6 $group   //group by 将集合中的文档分组,可用于统计结果
 7 $sort    //order by 将输入文档排序后输出
 8 $geoNear // 输出接近某一地理位置的有序文档
 9 
10 db.<collection>.aggregate(AGGREGATE_OPERATION)
11 //示例
12 // SELECT column_name,COUNT(column_name) AS total FROM kr GROUP BY column_name
13 db.kr.aggregate([
14     {$group:{_id:"$column_name",total:{$sum:1}}}
15 ])
16 // 按照column_name和article_id进行聚合
17 db.kr.aggregate([
18     {$group : {_id : {key1:"$column_name", key2:"$article_id"}, num_total : {$sum : 1}}}
19 ])
20 db.runoob.aggregate([{$project:{title:1,url:1,_id:0}}])            // 显示title、url字段
21 db.runoob.aggregate([{$match:{likes:{$gt:100,$lte:1500}}}])        // 筛选100<likes<=1500的文档
22 db.runoob.aggregate([{$skip:10}])                                  // 跳过前10个文档
23 db.runoob.aggregate([{$limit:3}])                                  // 显示前三个文档
24 db.runoob.aggregate([{$unwind:"$tags"}])                           // tags字段是数组类型,将其进行拆分
25 db.runoob.aggregate([{$sort:{likes:1}}])                           // 按likes字段升序排列,1代表升序,-1代表降序
  • aggregate()方法中$group中的修饰符
1 $sum        // sum()/count() 对设置的属性按分组计算总和,如果不是数值类型,则结果为0,设置为1,则为count(*)计数统计
2 $avg        // 对设置的属性按分组计算平均值,如果不是数值类型,则返回null
3 $min        // 获取集合中所有文档对应值得最小值, 分组取最小
4 $max        // 获取集合中所有文档对应值得最大值, 分组取最大
5 $push       // 在结果文档中插入值到一个数组中,将聚合之后的结果形成一个数组,如果按某个属性聚合之后,对A属性进行push,这把分组中所有的A属性放在一个数组里面
6 $addToSet   // 在结果文档中插入值到一个数组中,但不创建副本
7 $first      // 根据资源文档的排序获取每个分组第一个文档数据
8 $last       // 根据资源文档的排序获取每个分组最后一个文档数据
  • mapReduce(),V2.4加入
    • 关系数据的group不支持分布式运算,而且在单台服务器的运算能力必然是有限的,而mapReduce支持分布式运算,可以在大量的服务器上同时工作,以空间换结果
    • map函数首先按照分组的属性进行分组,将同属于一个组的数据映射到一个数组上去,reduce函数则是将分好的数组进行计算
    • 大坑:分组数据如果大于100,那么它每次取完100条,归并为1条,又返回给map函数作为输入,判断是否余数是否大于100,大于100,取100条,周而复始,直到最后一次取数不大于100,运算完成后就结束
    • 坑:使用Group或MapReduce时,如果一个分类只有一个元素,那么Reduce函数将不会执行,但Finalize函数还是会执行的;这时要在Finalize函数中考虑一个元素与多个元素返回结果的一致性
    • 示例在SQL_DB中Learn11.js、Learn12.js
 1 db.<collecton>.mapReduce(
 2     function(){    emit(key, value);},                // map函数,映射函数,key为统计的键,可以自定义;value为需要添加到数组的值的属性,可以多个
 3     function(key, values){ return reduceFunction },        // reduce统计函数,key为统计的键;values为数组
 4     {
 5         out: <collection>,        // 统计结果放在集合中,如果不指定out:{inline:1}则使用临时集合,在客户端断开后自动删除
 6         query: <document>,        // 筛选条件,只有符合条件的数据才会发到map函数
 7         sort: <document>,         // 排序后发给map函数
 8         limit: <number>,          // 发给map函数的数据数量                
 9         finalize: <function>,     // 在reduce函数执行完后执行,将键和文档作为参数,返回修改的文档
10         scope: <document>,        // 指定map、reduce、finalize的全局变量
11         jsMode: <boolean>,        // 指定是否在执行map和reduce函数直接将中间数据转换为BSON格式,默认为false,将map发出的js对象转换为BSON对象,调用reduce将BSON对象转换为js对象
12         verbose: <boolean>,       // 指定是否包含timing信息,默认为false,不包含
13         bypassDocumentValidation: <boolean>        // 是否允许mapReduce在操作期间绕过文档验证,这使得可以插入不符合验证要求的文档
14     }
15 )
  • aggregate():聚合表达式中使用的字符串运算符和算术运算符
 1 $add           // 计算数值的总和。例如:valuePlus5:{$add:["$value",5]}
 2 $divide        // 给定两个数值,用第一个数除以第二个数。例如:valueDividedBy5:{$divide:["$value",5]}
 3 $mod           // 取模。例如:{$mod:["$value",5]}
 4 $multiply      // 计算数值数组的乘积。例如:{$multiply:["$value",5]}
 5 $subtract      // 给定两个数值,用第一个数减去第二个数。例如:{$subtract:["$value",5]}
 6 $concat        // 连接两个字符串 例如:{$concat:["str1","str2"]}
 7 $strcasecmp    // 比较两个字符串并返回一个整数来反应比较结果。例如 {$strcasecmp:["$value","$value"]}
 8 $substr        // 返回字符串的一部分。例如:hasTest:{$substr:["$value","test"]}
 9 $toLower       // 将字符串转化为小写
10 $toUpper       // 将字符串转化为大写
  • aggregate():时间关键字
 1 $dayOfYear         // 返回该日期是这一年的第几天 (全年 366 天)
 2 $dayOfMonth        // 返回该日期是这一个月的第几天 (1到31)
 3 $dayOfWeek         // 返回的是这个周的星期几 (1:星期日,7:星期六)
 4 $year              // 返回该日期的年份部分
 5 $month             // 返回该日期的月份部分 (1到12)
 6 $week              // 返回该日期是所在年的第几个星期 (0到53)
 7 $hour              // 返回该日期的小时部分
 8 $minute            // 返回该日期的分钟部分
 9 $second            // 返回该日期的秒部分 (以0到59之间的数字形式返回日期的第二部分,但可以是60来计算闰秒)
10 $millisecond       // 返回该日期的毫秒部分 (0到999)
11 $dateToString      // { $dateToString: {format:"",date:""} }
12 // %Y  Year (4 digits, zero padded)                    0000-9999
13 // %m  Month (2 digits, zero padded)                   01-12
14 // %d  Day of Month (2 digits, zero padded)            01-31
15 // %H  Hour (2 digits, zero padded, 24-hour clock)    00-23
16 // %M  Minute (2 digits, zero padded)                  00-59
17 // %S  Second (2 digits, zero padded)                  00-60
18 // %L  Millisecond (3 digits, zero padded)            000-999
19 // %j  Day of year (3 digits, zero padded)             001-366
20 // %w  Day of week (1-Sunday, 7-Saturday)              1-7
21 // %U  Week of year (2 digits, zero padded)            00-53
22 // %%  Percent Character as a Literal                  %
23 db.runoob.aggregate([{$project:{createDate:1,_id:0,dayOfYear:{$dayOfYear:"$createDate"},year:{$year:"$createDate"}}}])
24 db.runoob.aggregate([{$project:{createDate:1,_id:0,newdate:{$dateToString:{format:"%Y",date:"$createDate"}}}}])

原文地址:https://www.cnblogs.com/My-Sun-Shine/p/13511091.html