- 2024-02-13 16:01:35
- 3671 热度
- 0 评论
上篇文章中我们已经学习了 MongoDB 中几个基本的管道操作符,本文我们再来看看其他的管道操作符。
$group
基本操作
$group 可以用来对文档进行分组,比如我想将订单按照城市进行分组,并统计出每个城市的订单数量:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",count:{$sum:1}}}) |
我们将要分组的字段传递给 $group 函数的 _id
字段,然后每当查到一个,就给 count 加 1,这样就可以统计出每个城市的订单数量。
算术操作符
通过算术操作符我们可以对分组后的文档进行求和或者求平均数。比如我想计算每个城市订单运费总和,如下:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",totalFreight:{$sum:"$freight"}}}) |
先按地址分组,再求和。这里贴出部分查询结果,如下:
1 |
{ |
也可以计算每个城市运费的平均数,如下:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",avgFreight:{$avg:"$freight"}}}) |
先按地址分组,然后再计算平均数。
极值操作符
极值操作符用来获取分组后数据集的边缘值,比如获取每个城市最贵的运费,如下:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",maxFreight:{$max:"$freight"}}}) |
查询每个城市最便宜的运费:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",minFreight:{$min:"$freight"}}}) |
按城市分组之后,获取该城市第一个运费单:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",firstFreight:{$first:"$freight"}}}) |
获取分组后的最后一个运费单:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",lastFreight:{$last:"$freight"}}}) |
数据操作符
$addToSet 可以将分组后的某一个字段放到一个数组中,但是重复的元素将只出现一次,而且元素加入到数组中的顺序是无规律的,比如将分组后的每个城市的运费放到一个数组中,如下:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",freights:{$addToSet:"$freight"}}}) |
重复的 freight 将不会被添加进来。
$push 则对重复的数据不做限制,都可以添加进来,如下:
1 |
db.sang_collect.aggregate({$group:{_id:"$orderAddressL",freights:{$push:"$freight"}}}) |
$unwind
$unwind 用来实现对文档的拆分,可以将文档中的值拆分为单独的文档,比如我的数据如下:
1 |
{ |
使用 $unwind 命令将其拆分为独立文档,如下:
1 |
db.sang_books.aggregate({$unwind:"$books"}) |
拆分结果如下:
1 |
{ |
其他操作符
$sort 操作可以对文档进行排序,如下:
1 |
db.sang_collect.aggregate({$sort:{orderAddressL:1}}) |
用法和我们之前介绍普通搜索中的一致,可以按照存在的字段排序,也可以按照重命名的字段排序,如下:
1 |
db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$sort:{oa:-1}}) |
1 表示升序、-1 表示降序。
$limit 返回结果中的前 n 个文档,如下表示返回结果中的前三个文档:
1 |
db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$limit:3}) |
$skip 表示跳过前 n 个文档,比如跳过前 5 个文档,如下:
1 |
db.sang_collect.aggregate({$project:{oa:"$orderAddressL"}},{$skip:5}) |
$skip 的效率低,要慎用。
总结
在管道开始执行的阶段尽可能过滤掉足够多的数据,这样做有两个好处:
- 只有从集合中直接查询时才会使用索引,尽早执行过滤可以让索引发挥作用;
- 该过滤的数据过滤掉之后,也可以降低后面管道的执行压力。另外,MongoDB 不允许一个聚合操作占用过多的内存,如果有一个聚合操作占用了超过 20% 的内存,则会直接报错。
好了,MongoDB 中的管道操作符我们就先说到这里,小伙伴们有问题欢迎留言讨论。
参考资料:
- 《MongoDB权威指南第2版》
- Spring(403)
- Boot(208)
- Spring Boot(187)
- Spring Cloud(82)
- Java(82)
- Cloud(82)
- Security(60)
- Spring Security(54)
- Boot2(51)
- Spring Boot2(51)
- Redis(31)
- SQL(29)
- Mysql(25)
- Dalston(24)
- IDE(24)
- mongoDB(22)
- MVC(22)
- JDBC(22)
- IDEA(22)
- Web(21)
- CLI(20)
- Alibaba(19)
- SpringMVC(19)
- Docker(17)
- SpringBoot(17)
- Git(16)
- Eclipse(16)
- Vue(16)
- JPA(15)
- Apache(15)
- ORA(15)
- Tomcat(14)
- Linux(14)
- HTTP(14)
- Mybatis(14)
- Oracle(14)
- jdk(14)
- OAuth(13)
- Nacos(13)
- Pro(13)
- XML(13)
- JdbcTemplate(13)
- JSON(12)
- OAuth2(12)
- Data(12)
- int(11)
- Myeclipse(11)
- stream(11)
- not(10)
- Bug(10)
- Hystrix(9)
- ast(9)
- maven(9)
- Map(9)
- Swagger(8)
- APP(8)
- Bit(8)
- API(8)
- session(8)
- Window(8)
- windows(7)
- too(7)
- HTML(7)
- Github(7)
- JavaMail(7)
- Cache(7)
- File(7)
- IntelliJ(7)
- mail(7)
- Server(6)
- nginx(6)
- jar(6)
- ueditor(6)
- ehcache(6)
- UDP(6)
- RabbitMQ(6)
- and(6)
- star(6)
- Excel(6)
- Log4J(6)
- pushlet(6)
- apt(6)
- Freemarker(6)
- read(6)
- WebFlux(6)
- JSP(6)
- Bean(6)
- error(6)
- are(5)
- SVN(5)
- for(5)
- DOM(5)
- Sentinel(5)
- the(5)
- JWT(5)
- rdquo(5)
- PHP(5)
- Struts(5)
- string(5)
- script(5)