1.分页查询
skip+limit形式
mongo中可通过skip+limit来实现文档批量查询的分页逻辑实现,具体javaAPI代码操作如下
@Testvoid testSelect() {//1.保存测试数据for (int i = 1; i <= 10; i++) {Student student = new Student();student.setId(i);student.setName(i + "ftc");student.setAge(i);mongoTemplate.insert(student);}//2.验证数据存入long count = mongoTemplate.count(new Query(), Student.class);Assert.isTrue(10 == count);//3.限制条数查询Query query = new Query().limit(2);List<Student> students = mongoTemplate.find(query, Student.class);Assert.isTrue(2 == students.size());//4.跳过指定条数查询query = new Query().skip(5);Student student = mongoTemplate.findOne(query, Student.class);Assert.isTrue(6 == student.getAge());//5.分页查询int pageNum = 4;int pageSize = 2;query = new Query().skip((pageNum - 1) * pageSize).limit(pageSize);students = mongoTemplate.find(query, Student.class);Assert.isTrue(7 == students.get(0).getId());Assert.isTrue(8 == students.get(1).getId());}
PageRequest形式
PageRequest类路径:import org.springframework.data.domain.PageRequest;
具体javaAPI如下:
@Testvoid testSelect() {//1.保存测试数据for (int i = 1; i <= 10; i++) {Student student = new Student();student.setId(i);student.setName(i + "ftc");student.setAge(i);mongoTemplate.insert(student);}//2.验证数据存入long count = mongoTemplate.count(new Query(), Student.class);Assert.isTrue(10 == count);//3.分页查询int pageNum = 4;int pageSize = 2;PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);Query query = new Query().with(pageRequest);List<Student> students = mongoTemplate.find(query, Student.class);Assert.isTrue(7 == students.get(0).getId());Assert.isTrue(8 == students.get(1).getId());}
2.排序
springboot中通过Sort类来指定排序顺序,类路径:import org.springframework.data.domain.Sort;
具体代码如下
@Testvoid testSelect() {//1.保存测试数据for (int i = 1; i <= 10; i++) {Student student = new Student();student.setId(i);student.setName(i + "ftc");student.setAge(i);mongoTemplate.insert(student);}//2.验证数据存入long count = mongoTemplate.count(new Query(), Student.class);Assert.isTrue(10 == count);//3.单一排序查询Sort sort = Sort.by(Sort.Direction.DESC, "id");List<Student> students = mongoTemplate.find(new Query().with(sort), Student.class);Assert.isTrue(students.get(0).getAge() == 10);Assert.isTrue(students.get(9).getAge() == 1);//4.组合排序查询sort = Sort.by(Sort.Direction.ASC, "id").and(Sort.by(Sort.Direction.ASC, "age"));students = mongoTemplate.find(new Query().with(sort), Student.class);Assert.isTrue(students.get(0).getAge() == 1);Assert.isTrue(students.get(9).getAge() == 10);}
3.聚合
springboot中每个聚合管道符都封装了不同的Operation,最终将这些operation整和到一个Aggregation,
最终在查询时,使用Aggregation即可查询
具体javaAPI如下
@Testvoid testSelect() {//1.保存测试数据for (int i = 1; i <= 10; i++) {Student student = new Student();student.setId(i);student.setName(i + "ftc");student.setAge(i);student.setSex(i % 2 == 0 ? 1 : 0);mongoTemplate.insert(student);}//2.验证数据存入long count = mongoTemplate.count(new Query(), Student.class);Assert.isTrue(10 == count);//3.聚合操作,获取年龄总和GroupOperation groupOperation = Aggregation.group().sum("age").as("ageSum");TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);AggregationResults<JSONObject> aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);JSONObject result = aggregationResult.getUniqueMappedResult();Assert.isTrue(55 == result.getInt("ageSum"));//4.获取不同性别的人数groupOperation = Aggregation.group("sex").count().as("agePeopleSum");typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);List<JSONObject> results = aggregationResult.getMappedResults();Assert.isTrue(2 == results.size());Assert.isTrue(5 == results.get(0).getInt("agePeopleSum"));Assert.isTrue(5 == results.get(1).getInt("agePeopleSum"));//5.获取年龄平均值groupOperation = Aggregation.group().avg("age").as("aveAge");typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);result = aggregationResult.getUniqueMappedResult();Assert.isTrue(5.5 == result.getDouble("aveAge"));//6.计算年龄最大值groupOperation = Aggregation.group().max("age").as("maxAge");typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);result = aggregationResult.getUniqueMappedResult();Assert.isTrue(10 == result.getInt("maxAge"));//7.计算年龄大于3的总人数MatchOperation matchOperation = Aggregation.match(Criteria.where("age").gt(3));groupOperation = Aggregation.group().count().as("peopleSum");typedAggregation = Aggregation.newAggregation(Student.class, matchOperation, groupOperation);aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);result = aggregationResult.getUniqueMappedResult();Assert.isTrue(7 == result.getInt("peopleSum"));}
4.联合查询
mongo中虽然提供了lookup进行多表联查,但是个人还是觉得,mongo中能用嵌入式数据结构存储,还是优先使用嵌入式数据结构存储
嵌入式数据模型
- 定义学生,成绩实体类。学生属性中嵌套了成绩集合 ```java import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
/**
- @author 冯铁城 [17615007230@163.com]
- @date 2022-07-20 19:12:01
- @describe: MongoDB实体类
“@Document(collection = “student”)” 用于指定对应哪个集合 */ @Data @Document(collection = “student”) public class Student {
private long id;
private String name;
private int age;
/**
性别 1-男 0-女 */ private int sex;
private List
grades; } java import lombok.Data;
/**
- @author 冯铁城 [17615007230@163.com]
- @date 2022-07-25 18:26:51
@describe: */ @Data public class Grade {
private String name;
private Double score; } ```
直接查询即可获取到嵌套的成绩集合
@Testvoid testSelect() {//1.定义成绩集合List<Grade> grades = CollUtil.newArrayList();Grade grade = new Grade();grade.setName("语文");grade.setScore(77.7);grades.add(grade);grade = new Grade();grade.setName("数学");grade.setScore(66.8);grades.add(grade);grade = new Grade();grade.setName("英语");grade.setScore(99.3);grades.add(grade);//2.定义学生Student student = new Student();student.setAge(18);student.setSex(1);student.setName("冯铁城");student.setGrades(grades);//3.存储mongoTemplate.insert(student);Student result = mongoTemplate.findOne(new Query(), Student.class);Assert.isTrue(result.getAge() == student.getAge());Assert.isTrue(result.getName().equals(student.getName()));Assert.isTrue(result.getSex() == student.getSex());Assert.isTrue(JSONUtil.toJsonStr(result.getGrades()).equals(JSONUtil.toJsonStr(student.getGrades())));}
引用式数据模型
使用unwind管道符
使用unwind会将指定的聚合数组字段拆分为多条数据
定义成绩类,对应成绩文档 ```java import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document;
/**
- @author 冯铁城 [17615007230@163.com]
- @date 2022-07-25 18:26:51
@describe: */ @Data @Document(collection = “grade”) public class Grade {
private String id;
private String studentId;
private String name;
private Double score; } ```
- 定义学生类,对应学生文档 ```java import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document;
/**
- @author 冯铁城 [17615007230@163.com]
- @date 2022-07-20 19:12:01
- @describe: MongoDB实体类
“@Document(collection = “student”)” 用于指定对应哪个集合 */ @Data @Document(collection = “student”) public class Student {
private String id;
private String name;
private int age;
/**
性别 1-男 0-女 */ private int sex;
private Grade grade; } ```
使用lookup进行查询
@Testvoid testSelect() {//1.定义学生Student student = new Student();student.setAge(18);student.setSex(1);student.setName("冯铁城");student = mongoTemplate.insert(student);//2.定义成绩List<Grade> grades = CollUtil.newArrayList();Grade grade = new Grade();grade.setName("语文");grade.setScore(77.7);grade.setStudentId(student.getId());grades.add(grade);grade = new Grade();grade.setName("数学");grade.setScore(66.8);grade.setStudentId(student.getId());grades.add(grade);grade = new Grade();grade.setName("英语");grade.setScore(99.3);grade.setStudentId(student.getId());grades.add(grade);mongoTemplate.insert(grades, Grade.class);//3.定义lookup、unwind管道符LookupOperation lookupOperation = Aggregation.lookup("grade", "id", "student_id", "grade");UnwindOperation unwindOperation = Aggregation.unwind("grade");TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, lookupOperation, unwindOperation);//4.查询AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);List<Student> students = aggregate.getMappedResults();Console.log(JSONUtil.toJsonPrettyStr(students));}
验证

不使用unwind管道符
- 定义成绩类,对应成绩文档(与使用unwind一致,不做过多累述)
- 定义学生类,对应学生文档 ```java import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document;
import java.util.List;
/**
- @author 冯铁城 [17615007230@163.com]
- @date 2022-07-20 19:12:01
- @describe: MongoDB实体类
“@Document(collection = “student”)” 用于指定对应哪个集合 */ @Data @Document(collection = “student”) public class Student {
private String id;
private String name;
private int age;
/**
性别 1-男 0-女 */ private int sex;
private List
grades; } ```
使用lookup进行查询
@Testvoid testSelect() {//1.定义学生Student student = new Student();student.setAge(18);student.setSex(1);student.setName("冯铁城");student = mongoTemplate.insert(student);//2.定义成绩List<Grade> grades = CollUtil.newArrayList();Grade grade = new Grade();grade.setName("语文");grade.setScore(77.7);grade.setStudentId(student.getId());grades.add(grade);grade = new Grade();grade.setName("数学");grade.setScore(66.8);grade.setStudentId(student.getId());grades.add(grade);grade = new Grade();grade.setName("英语");grade.setScore(99.3);grade.setStudentId(student.getId());grades.add(grade);mongoTemplate.insert(grades, Grade.class);//3.定义lookup、unwind管道符LookupOperation lookupOperation = Aggregation.lookup("grade", "id", "student_id", "grades");TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, lookupOperation);//4.查询AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);Student result = aggregate.getUniqueMappedResult();Console.log(JSONUtil.toJsonPrettyStr(result));}
验证
控制台输入如图,多表联查成功
