MongoDB学习总结五(详细记录MongoDB Aggregation聚合框架常见操作)
本文详细记录使用Aggregation聚合框架对MongoDB数据库的常见操作,包含筛选project、过滤match、排序sort、分组group by、略过skip、限制limit和分页查询设计思路等等,文中仍然有部分地方未能够充分理解,如_id一直保持展示的状态,尽管经过project筛选,后期补充。相比较与MongoTemplate操作,Aggregation聚合操作更加便捷、代码更加简洁
简明:本文详细记录使用Aggregation聚合框架对MongoDB数据库常见操作,包括过滤、分组、求和、排序和分页设计实现等等。相比较于MongoTemplate,使用Aggregation对MongoDB操作更加便捷、方便,特别是分组求和、计算平均值情况等。
(文章持续更新------后期添加更多基本操作)(个人记录学习总结内容,若出现错误/改进地方,请指出/分享,共同学习进步!!!)
一、简介
1、聚合简介
MongoDB中聚合通常用来处理数据,如分组求和、求平均值和排序等,对实现数据复杂操作较为方便,简单来说:聚合就是通过对集合中的数据进行运算,转换为自己需要的形式。
与上篇文章使用MongoTemplate操作数据相比较,Aggregation聚合操作显得更加有优势和便捷,代码清晰简洁,优化查询语句。
2、聚合管道简介
简明:在Linux中,管道一般是将当前命令的执行结果作为下个命令执行的参数。
MongoDB聚合管道:将MongoDB文档在一个管道处理完毕后,将结果传递给下一个管道处理。简单来说:管道就是聚合的整个运算过程。
3、聚合管道常用的表达式(常用)
表达式 | 功能 | 等价SQL |
$match | 过滤数据,输出符合条件文档 | where |
$project | 修改输入文档结构(筛选展示文档的键) | 个人理解(select) |
$limit | 限制计算文档结果返回数 | limit |
$sort | 文档排序 | order by |
$group | 文档分组 | group by |
$skip | 跳过指定数量的文档 | skip |
$unwind | 展开数组(数组内容拆分显示) | 无 |
二、测试案例
测试数据如下:
1、实体类
简明:为简化代码,已引入Lombok依赖,省略Setter()、Getter()方法
简明:@Document注解指定数据存储/操作的集合是PersonCollection
import lombok.Getter;
import lombok.Setter;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
/**
* Person 实体类
*
* @Document注解 默认情况下,创建Person集合(可使用@Document注解指定创建集合PersonCollection)
*
* @author LBF
* @date 2022/1/18 11:18
*/
@Setter
@Getter
@Document(collection = "PersonCollection")
public class Person {
/** Id */
@Id
private ObjectId id;
/** 名字 */
private String name;
/** 年龄 */
private Integer age;
/** 地址 */
private String addr;
/** 手机号 */
private Integer phone;
/** 类别(测试用) */
private String type;
public Person(String name, Integer age, String addr, Integer phone, String type) {
this.name = name;
this.age = age;
this.addr = addr;
this.phone = phone;
this.type = type;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", addr='" + addr + '\'' +
", phone=" + phone +
", type='" + type + '\'' +
'}';
}
}
2、测试代码
注意:测试代码中,键值是指数据库文档的键,而不是指实体类的键值(没有使用反射机制)
(1)常见聚合查询------->match(过滤)、group by(分组)、sum(求和)、sort(排序)
/**
* 常见聚合查询 ---------- 1
* @return 个人封装的返回体
*/
@GetMapping("/findDocumentByAgg1")
public AjaxResult findDocumentByAgg1(){
// 初始化查询容器(用来构建查询条件)
Criteria criteria = new Criteria();
// 设置查询条件: 23 <= age <= 30
criteria.and("age").gte(23).lte(30);
// 构建聚合操作
Aggregation aggregation = Aggregation.newAggregation(
// 使用反射机制,此时的键就是指实体类
// Person.class,
// 利用构建的查询条件进行过滤数据
Aggregation.match(criteria),
// 根据 type 键分组 ------> 求和 age 键 --------> 每个分组的求和结果取个别名:totalAge
Aggregation.group("type").sum("age").as("totalAge"),
// 将分组求和的结果totalAge,按照降序排序
Aggregation.sort(Sort.by("totalAge").descending())
);
// 将拼接的聚合管道操作传入
// 第一个参数:aggregation聚合操作
// 第二个参数:操作的集合名称
// 第三个参数:输出类型(此处使用Document,包含_id键情况下使用实体类Person会类型转换报错)
AggregationResults<Document> results =
mongoTemplate.aggregate(aggregation,"PersonCollection",Document.class);
return AjaxResult.success(results.getMappedResults());
}
(2)常见聚合查询------->project(展示键)、skip(跳过)
@GetMapping("/findDocumentByAgg2")
public AjaxResult findDocumentByAgg2(){
// 初始化查询容器(用来构建查询条件)
Criteria criteria = new Criteria();
// 设置查询条件: 23 <= age <= 30
criteria.and("age").gte(23).lte(30);
Aggregation aggregation = Aggregation.newAggregation(
// 过滤数据
Aggregation.match(criteria),
// 选择结果需要展示的字段(默认是全展示,_id键会显示)
Aggregation.project("name","addr"),
// 跳过1个结果,显示剩余,即剩余1个结果
Aggregation.skip(1)
);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation,"PersonCollection",Document.class);
return AjaxResult.success(results.getMappedResults());
}
(3)常见聚合查询------->(分页查询,以查询第2页为例)(首页第1页)
Aggregation聚合分页查询思路: skip跳过2个数据,limit每页显示最大文档数2个,跳过1、2个数据,即显示第3、4个数据,因此就显示第2页。
/** Aggregation 分页查询 */
@GetMapping("/findDocumentByAgg3")
public AjaxResult findDocumentByAgg3(){
// 构建聚合操作
Aggregation aggregation = Aggregation.newAggregation(
// 展示的键 name phone _id键会显示
Aggregation.project("name","phone"),
// 跳过某数量的数据,显示剩余(可理解为显示的第几页,如以下:跳过3个,显示第2页)
// 计算思路:skip((页码-1)* maxElements)
Aggregation.skip(1*2),
// 利用limit:限制输出的文档数,即需展示的数据量(可理解为每页显示的数量)
Aggregation.limit(2)
);
AggregationResults<Document> results = mongoTemplate.aggregate(aggregation,"PersonCollection",Document.class);
return AjaxResult.success(results.getMappedResults());
}
(4)常见聚合查询------->(持续补充)
三、总结
本文记录个人使用Aggregation聚合框架时,一些经常使用到的操作表达式,仍然存在部分地方未能够充分理解进行解释,若文中出现错误/需改进的地方,请指出/分享,共同学习进步!!!
更多推荐
所有评论(0)