Java MongoDB:(十六)MongoDB 的文档操作-MongoDB 聚合查询-7100字匠心出品

  • 在 MongoDB 中我们可以通过 aggregate()函数来完成一些聚合查询,aggregate()函数主要用于处理诸如统计,平均值,求和等,并返回计算后的数据结果
  • 语法格式:
    db.COLLECTION_NAME.aggregate([{$ group:{_id:"$ 分组键名","$ 分组键名",…,别名:{聚合运算:"$运算列"}}},{条件筛选:{键名:{运算条件:运算值}}}])
  • 常见的 mongo 的聚合操作和 mysql 的查询做类比
    设置

1.求和 - $sum

  • 查询 dev 集合中一共有多少个文档。
  • 相当于 sql 语句:SELECT count(*) AS count FROM dev
  • db.dev.aggregate([{$ group:{_id:null,count:{$sum:1}}}])
  • $group:分组,代表聚合的分组条件
  • _id:分组的字段。相当于 SQL 分组语法 group by column_name 中的 column_name 部分。如果根据某字段的值分组,则定义为_id:’$字段名’。所以此案例中的 null 代表一个固定的字面值’null’。
  • count:返回结果字段名。可以自定义,类似 SQL 中的字段别名
  • $sum:求和表达式。相当于 SQL 中的 sum()
  • 1:累加值。
    设置
  • 查询 dev 集合中的所有 size 键中的值的总和
  • 相当于 sql 语句:SELECT sum(size) AS totalSize FROM dev
  • db.dev.aggregate([{$ group:{_id:null,totalSize:{$ sum:"$size"}}}])
  • “$size”:代表文档中的 szie 字段的值。
    设置
  • 对每一个 title 进行分组并计算每组中的 size 的总和
  • 相当于 sql 语句:SELECT title AS _id , sum(size) AS totalSize FROM dev GROUP BY title
  • db.dev.aggregate([{$ group:{_id:"$ title",totalSize:{$ sum:"$size"}}}])
    设置

2.条件筛选 - $match

  • 查询 dev 集合有多少文档的 size 大于 200
  • db.dev.aggregate([{$ match:{size:{$ gt:200}}},{$ group:{_id:null,totalSize:{$sum:1}}}])
  • 相当于 SQL 语句:SELECT count(*) FROM dev WHERE size > 200
  • $match:匹配条件,相当于 SQL 中的 where 子句,代表聚合之前进行条件筛选
    设置
  • 查询 dev 集合,根据 title 分组计算出每组的 size 的总和,并过滤掉总和小于等于 200的文档。
  • db.dev.aggregate([{$ group:{_id:"$ title",totalSize:{$ sum:"$ size"}}},{$ match:{totalSize:{$gt:200}}}])
  • 相当于 SQL 语句:SELECT sum(size) AS totalSize FROM dev GROUP BY title HAVING totalSize > 200
    设置

3.最大值 - $max

  • 查询 dev 集合中 size 最大的文档
  • db.dev.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …:null,maxSize:{max:"$size"}}}])
  • $ max:"$size":计算 size 键中的最大值。
  • 相当于 SQL 语句:SELECT max(size) FROM dev
    设置

4.最小值 - $min

  • 查询 dev 集合中 size 最小的文档。
  • db.dev.aggregate([{$ group:{_id:null,minSize:{$ min:"$size"}}}])
  • $ min:"$size":计算 size 键中的最小值。
  • 相当于 SQL 语句:SELECT min(size) FROM dev
    设置

5.平均值 - $avg

  • 查询 dev 集合中 size 的平均值
  • db.dev.aggregate([{$ group:{_id:null,sizeAvg:{$ avg:"$size"}}}])
  • $ avg:"$size":计算 size 键的平均值
  • 相当于 SQL 语句:SELECT avg(size) FROM dev
    设置

6.统计结果返回数组 - $push

  • 查询 dev 集合,按照 size 分组并返回他们的 title,如果 size 相同则使用数组返回他们的title。
  • db.dev.aggregate([{$ group:{_id:"$ size",title:{$ push:"$title"}}}])
  • $ push:"$title":如果 size 相同则使用数组返回他们不同的 title
    设置

7.数组字段拆分 - $unwind

  • 查询 dev 集合,将数组中的内容拆分显示
  • db.dev.aggregate([{$ unwind:"$tags"}])
  • $ unwind:"$tags":对数组中的元素进行拆分显示
    设置

8.管道操作

  • 什么是管道操作:
  • 管道在 Unix 和 Linux 中一般用于将当前命令的输出结果作为下一个命令的参数
  • MongoDB 的聚合管道将 MongoDB 文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的
  • 管道操作符是按照书写的顺序依次执行的,每个操作符都会接受一连串的文档,对这些文档做一些类型转换,最后将转换后的文档作为结果传递给下一个操作符(对于最后一个管道操作符,是将结果返回给客户端),称为流式工作方式。
  • 管道操作符:$ match、$ group、$ sort、$ limit、$ skip、$unwind
  • 管道操作符,只能用于计算当前聚合管道的文档,不能处理其它的文档。

8.1 $project-聚合投影约束

  • $ project 操作符:我们可以使用$project 操作符做聚合投影操作。
  • 查询 dev 集合,将数组中的内容拆分显示,并只显示 title 键与 tags 键的值
  • db.dev.aggregate([{$ unwind:"$ tags"},{$ project:{_id:0,tags:"$ tags",title:"$title"}}])
  • tags:"$tags":显示 tags 的值,字段名为 tags。
  • title:"$title":显示 title 的值,字段名为 title。
    设置
  • 查询 dev 集合,将数组中的内容拆分显示。要求只显示 title 键与 tags 键的值并将 title键修改为 Title。
  • db.dev.aggregate([{$ unwind:"$ tags"},{$ project:{_id:0,tags:"$ tags",Title:"$title"}}])
  • Title:"$title":显示 title 的值,字段名为 Title。
    设置

8.2 $project-字符串处理

  • 在$project 中我们可以通过 MongoDB 的字符串操作符对投影的内容做字符串处理。
  • 查询 dev 集合,将数组中的内容拆分显示。将 title 中的值换为小写并命名为 New_Title, 将 tags 的转换为大写并命名为 New_Tags。
  • db.dev.aggregate([{$ unwind:"$ tags"},{ $ project:{_id:0,New_Title:{$ toLower:"$ title"},New_tags:{$ toUpper:"$tags"}}}])
  • New_Title:{$ toLower:"$title"}:将 title 的值转换为小写,显示字段名为 New_Title。
  • New_tags:{$ toUpper:"$tags"}:将 tags 的值转换为大写,显示字段名为 New_Tags。
    设置
  • 查询 dev 集合,将数组中的内容拆分显示。将 title 字段和 tags 字段的值拼接为一个完整字符串并在 Title_Tags 字段中显示。
  • db.dev.aggregate([{$ unwind:"$ tags"},{$ project:{_id:0,Title_Tags:{$ concat:["$ title","-","$tags"]}}}])
  • Title_Tags:{$ concat:["$ title","-","$tags"]}:将字段 title 与字符串’-'和字段 tags 的值拼接为新的字符串,并显示字段名为 Title_Tags
    设置
  • 查询 dev 集合,将数组中的内容拆分显示。只显示 title 字段的前 3 个字符,并命名为Title_Prefix
  • db.dev.aggregate([{$ unwind:"$ tags"},{$ project:{_id:0,Title_Prefix:{$ substr:["$title",0,3]}}}])
  • Title_Prefix:{$ substr:["$title",0,3]}:将 title 的值从0 开始截取截3 位,并命名为 Title_Prefix
    设置
  • 我们可以看到对于汉字部分并未截取三位,原因是$ substr 只能匹配 ASCII 的数据,对于中文要使用$substrCP
    设置

8.3 $project-算术运算

  • 在$project 中我们可以通过 MongoDB 的算数作符对投影的内容做运算处理。
  • 查询 dev 集合中数据,显示 title 和 size 字段,为 size 字段数据做加 1 操作,显示字段命名为 New_Size。
  • db.dev.aggregate([{$ project:{_id:0,title:1,New_Size:{$ add:["$size",1]}}}])
  • New_Size:{$ add:["$size",1]}:在查询结果中,对size的值做加1处理,并命名为New_Size。
    设置
  • 排除那些没有 size 键的文档。
  • db.dev.aggregate([{$ match:{size:{$ ne:null}}},{$ project:{_id:0,title:1,New_Size:{$ add:["$size",1]}}}])
  • $ match:{size:{$ne:null}:排除那些没有 size 的文档。
    设置
  • 查询 dev 集合中数据,显示 title 和 size 字段,为 size 字段数据做减 1 操作,显示字段命名为 New_Size。
  • db.dev.aggregate([{$ match:{size:{$ ne:null}}},{$ project:{_id:0,title:1,New_Size:{$ subtract:["$size",1]}}}])
  • New_Size:{$ subtract:["$size",1]}:在查询结果中,对 size 的值做减 1 处理,并命名为New_Size。
    设置
  • 查询 dev 集合中数据,显示 title 和 size 字段,为 size 字段数据做乘 2 操作,显示字段命名为 New_Size。
  • db.dev.aggregate([{$ match:{size:{$ ne:null}}},{$ project:{_id:0,title:1,New_Size:{$ multiply:["$size",2]}}}])
  • New_Size:{$ multiply:["$size",2]}:在查询结果中,对 size 的值做乘 2 处理,并命名为New_Size.
    设置
  • 查询 dev 集合中数据,显示 title 和 size 字段,为 size 字段数据做除 2 操作,显示字段命名为 New_Size。
  • db.dev.aggregate([{$ match:{size:{$ ne:null}}},{$ project:{_id:0,title:1,New_Size:{$ divide:["$size",2]}}}])
  • New_Size:{$ divide:["$size",2]}:在查询结果中,对 size 的值做除 2 处理,并命名为New_Size
    设置
  • 查询 dev 集合中数据,显示 title 和 size 字段,为 size 字段数据做模 2 操作,显示字段命名为 New_Size
  • db.dev.aggregate([{$ match:{size:{$ ne:null}}},{$ project:{_id:0,title:1,New_Size:{$ mod:["$size",2]}}}])
  • New_Size:{$ mod:["$size",2]}:在查询结果中,对size的值做模2处理,并命名为New_Size
    设置

8.4 $project-日期操作

8.4.1 MongoDB 中的日期处理

  • 插入当前时间 db.dev.insert({date:new Date()})
  • MongoDB 中的时间会比系统当前时间少 8 个小时。因为他的时间是 UTC 的时间,而中国的时区是东八区,比 UTC 快 8 个小时,所以会比当前时间少 8 个小时。
    设置
  • 插入指定日期
  • 方式一:
    db.dev.insert({time:new Date(“2018-05-01T14:20:23Z”)})
    new Date(“2018-05-01T14:20:23Z”):创建时间对象,日期格式为 yyyy-MM-ddThh:mm:ss
    设置
  • 方式二:
    db.dev.insert({time:ISODate(“2019-06-01T16:30:00Z”)})
    ISODate(“2019-06-01T16:30:00Z”):
    设置
  • 查询时间
  • db.dev.find({time:{$eq:new Date(“2018-05-01T14:20:23”)}})
    设置
  • 或者
  • db.dev.find({time:{$gt:new Date(“2018-04-01”)}})
    设置
  • 或者
    设置

8.4.2 $project-日期处理

  • 向 dev 集合中插入一个文档,该文档包含 name:”admin” birth:”1990-05-01T13:30:00Z”
    设置
  • 查询 dev 集合中数据,显示 birth 字段的各部分数据,包括:年、月、日等信息。
  • 显示年月日
  • db.dev.aggregate([{$ match:{name:“admin”}},{$ project:{ 年 份 :{$ year:"$ birth"}, 月 份:{$ month:"$ birth"}日:{$ dayOfMonth:"$birth"}}}])
  • {$ year:"$birth"}年份
  • {$ month:"$birth"}月份
  • {$ dayOfMonth:"$birth"}日期
    设置
  • 显示小时、分钟、秒、毫秒
  • db.dev.aggregate([{$ match:{name:“admin”}},{$ project:{ 年 份 :{$ year:"$ birth"}, 月 份 {$ month:"$ birth"}, 日 :{$ dayOfMonth:"$ birth"}, 时 :{$ hour:"$ birth"}, 分 :{$ minute:"$ birth"},秒:{$ second:"$ birth"},毫秒:{$ millisecond:"$birth"}}}])
  • {$ hour:"$birth"}:小时
  • {$ minute:"$birth"}:分钟
  • {$ second:"$birth"}:秒
  • {$ millisecond:"$birth"}:毫秒
    设置
  • 显示星期、全年的第几周、全年中的第几天
  • db.dev.aggregate([{$ match:{name:“admin”}},{$ project:{ 年 份 :{$ year:"$ birth"}, 月 份 {$ month:"$ birth"}, 日 :{$ dayOfMonth:"$ birth"}, 时 :{$ hour:"$ birth"}, 分 :{$ minute:"$ birth"},秒:{$ second:"$ birth"},毫秒:{$ millisecond:"$ birth"},星期:{$ dayOfWeek:"$ birth"},全年的第几周:{$ week:"$ birth"},全年中的第几天:{$ dayOfYear:"$birth"}}}])
  • {$ dayOfWeek:"$birth"}:星期日为 1,星期六为 7。
  • {$ week:"$birth"}:全年的周计数从 0 开始。
  • {$ dayOfYear:"$birth"}:全年中的第几天。
    设置
  • 显示自定义日期格式
  • db.dev.aggregate([{$ match:{name:“admin”}},{$ project:{ 年 份 :{$ year:"$ birth"}, 月 份 {$ month:"$ birth"}, 日 :{$ dayOfMonth:"$ birth"}, 时 :{$ hour:"$ birth"}, 分 :{$ minute:"$ birth"},秒:{$ second:"$ birth"},毫秒{$ millisecond:"$ birth"},星期:{$ dayOfWeek:"$ birth"},全年的第几周 :{$ week:"$ birth"}, 全 年 中 的 第 几 天:{$ dayOfYear:"$ birth"}, 自 定 义 日 期 格式:{$ dateToString:{format:"%Y 年%m 月%d 日%H:%M:%S",date:"$birth"}}}}])
  • {$ dateToString:{format:"%Y 年%m月%d 日 %H:%M:%S",date:"$birth"}:自定义日期格式
  • 具体格式如下:
    设置
    设置