MongoDB管道

作者: 缘来是你ylh | 来源:发表于2019-03-08 06:15 被阅读20次

今天和大家分享mongodb中管道,老规矩贴上官方 文档

我们从聚合慢慢引入管道的概念

mongo中常见的聚合有count,distinct,group,mapReduce

我们先创建好测试数据,查看一下

> db.student.find().pretty()
{ "_id" : 1, "name" : "tom", "age" : 20, "scores" : 98 }
{ "_id" : 2, "name" : "jack", "age" : 21, "scores" : 89 }
{ "_id" : 3, "name" : "lucy", "age" : 19, "scores" : 91 }
{ "_id" : 4, "name" : "luna", "age" : 21, "scores" : 91 }

下面来介绍个方法的使用

1.count 统计文档数量

> db.student.count()    //统计文档数量
4
> db.student.count({"age": {$gte: 20}})   //统计年龄大于等于20的文档数量
3

2.countDocuments

mongo4.0以上的版本已经不推荐使用count了,取而代之的是countDocuments

> db.student.countDocuments({"age": {$gte: 20}})
3

3.distinct 获取指定字段的值的分布(去重)

> db.student.distinct("scores")
[ 98, 89, 91 ]    

4.aggregate(管道)替代group,老板本mongo是有直接的命令group来分组的

官方原文

DEPRECATED SINCE VERSION 3.4

Mongodb 3.4 deprecates the group command. Use db.collection.aggregate() with the $group stage or db.collection.mapReduce() instead.

mongodb3.4版本废弃了group命令,取而代之的是db.collection.aggregatedb.collection.mapReduce

> db.student.aggregate([ {$group: {_id: "$scores", person_num : {$sum: "$scores"}}} ])
{ "_id" : 91, "person_num" : 182 }
{ "_id" : 89, "person_num" : 89 }
{ "_id" : 98, "person_num" : 98 }

类似于mysql的 select scores, count(*) as person_num from student group by scores

$sum后面的是什么意思呢,对scores字段求和

> db.student.aggregate([ 
    {$match: {"name": {$in: ["tom", "jack", "luna"]}}},  
    {$group: {_id: "$scores", person_num : {$sum: 1}}} 
])
{ "_id" : 91, "person_num" : 1 }
{ "_id" : 89, "person_num" : 1 }
{ "_id" : 98, "person_num" : 1 }

这里就是一个典型的管道使用情况了, 以上命令执行了两步,在一个管道里面执行

  • 先匹配name值在数组["tom", "jack", "luna"]的文档
  • 再分组统计

既然说到了分组group我就顺便再讲几个聚合方法吧

根据年龄分组求平均值实例

> db.student.find()
{ "_id" : 1, "name" : "tom", "age" : 20, "scores" : 98 }
{ "_id" : 2, "name" : "jack", "age" : 21, "scores" : 89 }
{ "_id" : 3, "name" : "lucy", "age" : 19, "scores" : 91 }
{ "_id" : 4, "name" : "luna", "age" : 21, "scores" : 91 }
> db.student.aggregate([{$group : {_id: "$age", avg_scores: {$avg: "$scores"}}}])
{ "_id" : 19, "avg_scores" : 91 }
{ "_id" : 21, "avg_scores" : 90 }
{ "_id" : 20, "avg_scores" : 98 }

根据分数分组,求组内最小的分数

> db.student.aggregate([{$group : {_id: "$scores", min_scores: {$min: "$age"}}}])
{ "_id" : 91, "min_scores" : 19 }
{ "_id" : 89, "min_scores" : 21 }
{ "_id" : 98, "min_scores" : 20 }

对应的$max方法语法一直

总结:

表达式 描述 语法
$sum 计算总和 db.mycol.aggregate([{group : {_id : "by_field", alias_name : {sum : "field"}}}])
$avg 计算平均值 db.mycol.aggregate([{group : {_id : "by_field", alias_name : {avg : "field"}}}])
$min 获取集合中所有文档对应值得最小值 db.mycol.aggregate([{group : {_id : "by_field", alias_name : {min : "field"}}}])
$max 获取集合中所有文档对应值得最大值 db.mycol.aggregate([{group : {_id : "by_field", alias_name : {max : "field"}}}])

$by_field是分组的字段,比如按年龄分组就改成$age

alias_name 是统计数据之后的一个别名,类似于mysql的as

$field 是聚合的字段 比如按年龄分组后取分组中scores的最大值就把$field改为$scores

管道中的排序

文档的排序也是要通过管道来实现的

> db.student.aggregate([{$sort : {age : 1}}])
{ "_id" : 3, "name" : "lucy", "age" : 19, "scores" : 91 }
{ "_id" : 1, "name" : "tom", "age" : 20, "scores" : 98 }
{ "_id" : 2, "name" : "jack", "age" : 21, "scores" : 89 }
{ "_id" : 4, "name" : "luna", "age" : 21, "scores" : 91 }

官方原文

For the field or fields to sort by, set the sort order to 1 or -1 to specify an ascending or descending sort respectively, as in the following example:

1是升序asc,-1是降序desc

最后说一下管道中的其它操作

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档

本文写的有点乱,希望看官不要见怪!!!

相关文章

网友评论

    本文标题:MongoDB管道

    本文链接:https://www.haomeiwen.com/subject/wqhpuqtx.html