- 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 // 将字符串转化为大写
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://img2020.cnblogs.com/blog/1378165/202008/1378165-20200815235601015-446254759.png)