1.分页查询

skip+limit形式

mongo中可通过skip+limit来实现文档批量查询的分页逻辑实现,具体javaAPI代码操作如下

  1. @Test
  2. void testSelect() {
  3. //1.保存测试数据
  4. for (int i = 1; i <= 10; i++) {
  5. Student student = new Student();
  6. student.setId(i);
  7. student.setName(i + "ftc");
  8. student.setAge(i);
  9. mongoTemplate.insert(student);
  10. }
  11. //2.验证数据存入
  12. long count = mongoTemplate.count(new Query(), Student.class);
  13. Assert.isTrue(10 == count);
  14. //3.限制条数查询
  15. Query query = new Query().limit(2);
  16. List<Student> students = mongoTemplate.find(query, Student.class);
  17. Assert.isTrue(2 == students.size());
  18. //4.跳过指定条数查询
  19. query = new Query().skip(5);
  20. Student student = mongoTemplate.findOne(query, Student.class);
  21. Assert.isTrue(6 == student.getAge());
  22. //5.分页查询
  23. int pageNum = 4;
  24. int pageSize = 2;
  25. query = new Query().skip((pageNum - 1) * pageSize).limit(pageSize);
  26. students = mongoTemplate.find(query, Student.class);
  27. Assert.isTrue(7 == students.get(0).getId());
  28. Assert.isTrue(8 == students.get(1).getId());
  29. }

PageRequest形式

PageRequest类路径:import org.springframework.data.domain.PageRequest;
具体javaAPI如下:

  1. @Test
  2. void testSelect() {
  3. //1.保存测试数据
  4. for (int i = 1; i <= 10; i++) {
  5. Student student = new Student();
  6. student.setId(i);
  7. student.setName(i + "ftc");
  8. student.setAge(i);
  9. mongoTemplate.insert(student);
  10. }
  11. //2.验证数据存入
  12. long count = mongoTemplate.count(new Query(), Student.class);
  13. Assert.isTrue(10 == count);
  14. //3.分页查询
  15. int pageNum = 4;
  16. int pageSize = 2;
  17. PageRequest pageRequest = PageRequest.of(pageNum - 1, pageSize);
  18. Query query = new Query().with(pageRequest);
  19. List<Student> students = mongoTemplate.find(query, Student.class);
  20. Assert.isTrue(7 == students.get(0).getId());
  21. Assert.isTrue(8 == students.get(1).getId());
  22. }

2.排序

springboot中通过Sort类来指定排序顺序,类路径:import org.springframework.data.domain.Sort;
具体代码如下

  1. @Test
  2. void testSelect() {
  3. //1.保存测试数据
  4. for (int i = 1; i <= 10; i++) {
  5. Student student = new Student();
  6. student.setId(i);
  7. student.setName(i + "ftc");
  8. student.setAge(i);
  9. mongoTemplate.insert(student);
  10. }
  11. //2.验证数据存入
  12. long count = mongoTemplate.count(new Query(), Student.class);
  13. Assert.isTrue(10 == count);
  14. //3.单一排序查询
  15. Sort sort = Sort.by(Sort.Direction.DESC, "id");
  16. List<Student> students = mongoTemplate.find(new Query().with(sort), Student.class);
  17. Assert.isTrue(students.get(0).getAge() == 10);
  18. Assert.isTrue(students.get(9).getAge() == 1);
  19. //4.组合排序查询
  20. sort = Sort.by(Sort.Direction.ASC, "id").and(Sort.by(Sort.Direction.ASC, "age"));
  21. students = mongoTemplate.find(new Query().with(sort), Student.class);
  22. Assert.isTrue(students.get(0).getAge() == 1);
  23. Assert.isTrue(students.get(9).getAge() == 10);
  24. }

3.聚合

springboot中每个聚合管道符都封装了不同的Operation,最终将这些operation整和到一个Aggregation,
最终在查询时,使用Aggregation即可查询
具体javaAPI如下

  1. @Test
  2. void testSelect() {
  3. //1.保存测试数据
  4. for (int i = 1; i <= 10; i++) {
  5. Student student = new Student();
  6. student.setId(i);
  7. student.setName(i + "ftc");
  8. student.setAge(i);
  9. student.setSex(i % 2 == 0 ? 1 : 0);
  10. mongoTemplate.insert(student);
  11. }
  12. //2.验证数据存入
  13. long count = mongoTemplate.count(new Query(), Student.class);
  14. Assert.isTrue(10 == count);
  15. //3.聚合操作,获取年龄总和
  16. GroupOperation groupOperation = Aggregation.group().sum("age").as("ageSum");
  17. TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);
  18. AggregationResults<JSONObject> aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);
  19. JSONObject result = aggregationResult.getUniqueMappedResult();
  20. Assert.isTrue(55 == result.getInt("ageSum"));
  21. //4.获取不同性别的人数
  22. groupOperation = Aggregation.group("sex").count().as("agePeopleSum");
  23. typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);
  24. aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);
  25. List<JSONObject> results = aggregationResult.getMappedResults();
  26. Assert.isTrue(2 == results.size());
  27. Assert.isTrue(5 == results.get(0).getInt("agePeopleSum"));
  28. Assert.isTrue(5 == results.get(1).getInt("agePeopleSum"));
  29. //5.获取年龄平均值
  30. groupOperation = Aggregation.group().avg("age").as("aveAge");
  31. typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);
  32. aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);
  33. result = aggregationResult.getUniqueMappedResult();
  34. Assert.isTrue(5.5 == result.getDouble("aveAge"));
  35. //6.计算年龄最大值
  36. groupOperation = Aggregation.group().max("age").as("maxAge");
  37. typedAggregation = Aggregation.newAggregation(Student.class, groupOperation);
  38. aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);
  39. result = aggregationResult.getUniqueMappedResult();
  40. Assert.isTrue(10 == result.getInt("maxAge"));
  41. //7.计算年龄大于3的总人数
  42. MatchOperation matchOperation = Aggregation.match(Criteria.where("age").gt(3));
  43. groupOperation = Aggregation.group().count().as("peopleSum");
  44. typedAggregation = Aggregation.newAggregation(Student.class, matchOperation, groupOperation);
  45. aggregationResult = mongoTemplate.aggregate(typedAggregation, JSONObject.class);
  46. result = aggregationResult.getUniqueMappedResult();
  47. Assert.isTrue(7 == result.getInt("peopleSum"));
  48. }

4.联合查询

mongo中虽然提供了lookup进行多表联查,但是个人还是觉得,mongo中能用嵌入式数据结构存储,还是优先使用嵌入式数据结构存储

嵌入式数据模型

  1. 定义学生,成绩实体类。学生属性中嵌套了成绩集合 ```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; } ```

  1. 直接查询即可获取到嵌套的成绩集合

    1. @Test
    2. void testSelect() {
    3. //1.定义成绩集合
    4. List<Grade> grades = CollUtil.newArrayList();
    5. Grade grade = new Grade();
    6. grade.setName("语文");
    7. grade.setScore(77.7);
    8. grades.add(grade);
    9. grade = new Grade();
    10. grade.setName("数学");
    11. grade.setScore(66.8);
    12. grades.add(grade);
    13. grade = new Grade();
    14. grade.setName("英语");
    15. grade.setScore(99.3);
    16. grades.add(grade);
    17. //2.定义学生
    18. Student student = new Student();
    19. student.setAge(18);
    20. student.setSex(1);
    21. student.setName("冯铁城");
    22. student.setGrades(grades);
    23. //3.存储
    24. mongoTemplate.insert(student);
    25. Student result = mongoTemplate.findOne(new Query(), Student.class);
    26. Assert.isTrue(result.getAge() == student.getAge());
    27. Assert.isTrue(result.getName().equals(student.getName()));
    28. Assert.isTrue(result.getSex() == student.getSex());
    29. Assert.isTrue(JSONUtil.toJsonStr(result.getGrades()).equals(JSONUtil.toJsonStr(student.getGrades())));
    30. }

    引用式数据模型

    使用unwind管道符

    使用unwind会将指定的聚合数组字段拆分为多条数据

  2. 定义成绩类,对应成绩文档 ```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; } ```

  1. 定义学生类,对应学生文档 ```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; } ```

  1. 使用lookup进行查询

    1. @Test
    2. void testSelect() {
    3. //1.定义学生
    4. Student student = new Student();
    5. student.setAge(18);
    6. student.setSex(1);
    7. student.setName("冯铁城");
    8. student = mongoTemplate.insert(student);
    9. //2.定义成绩
    10. List<Grade> grades = CollUtil.newArrayList();
    11. Grade grade = new Grade();
    12. grade.setName("语文");
    13. grade.setScore(77.7);
    14. grade.setStudentId(student.getId());
    15. grades.add(grade);
    16. grade = new Grade();
    17. grade.setName("数学");
    18. grade.setScore(66.8);
    19. grade.setStudentId(student.getId());
    20. grades.add(grade);
    21. grade = new Grade();
    22. grade.setName("英语");
    23. grade.setScore(99.3);
    24. grade.setStudentId(student.getId());
    25. grades.add(grade);
    26. mongoTemplate.insert(grades, Grade.class);
    27. //3.定义lookup、unwind管道符
    28. LookupOperation lookupOperation = Aggregation.lookup("grade", "id", "student_id", "grade");
    29. UnwindOperation unwindOperation = Aggregation.unwind("grade");
    30. TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, lookupOperation, unwindOperation);
    31. //4.查询
    32. AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);
    33. List<Student> students = aggregate.getMappedResults();
    34. Console.log(JSONUtil.toJsonPrettyStr(students));
    35. }
  2. 验证

控制台输入如图,多表联查成功

image.png
不使用unwind管道符

  1. 定义成绩类,对应成绩文档(与使用unwind一致,不做过多累述)
  2. 定义学生类,对应学生文档 ```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; } ```

  1. 使用lookup进行查询

    1. @Test
    2. void testSelect() {
    3. //1.定义学生
    4. Student student = new Student();
    5. student.setAge(18);
    6. student.setSex(1);
    7. student.setName("冯铁城");
    8. student = mongoTemplate.insert(student);
    9. //2.定义成绩
    10. List<Grade> grades = CollUtil.newArrayList();
    11. Grade grade = new Grade();
    12. grade.setName("语文");
    13. grade.setScore(77.7);
    14. grade.setStudentId(student.getId());
    15. grades.add(grade);
    16. grade = new Grade();
    17. grade.setName("数学");
    18. grade.setScore(66.8);
    19. grade.setStudentId(student.getId());
    20. grades.add(grade);
    21. grade = new Grade();
    22. grade.setName("英语");
    23. grade.setScore(99.3);
    24. grade.setStudentId(student.getId());
    25. grades.add(grade);
    26. mongoTemplate.insert(grades, Grade.class);
    27. //3.定义lookup、unwind管道符
    28. LookupOperation lookupOperation = Aggregation.lookup("grade", "id", "student_id", "grades");
    29. TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, lookupOperation);
    30. //4.查询
    31. AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);
    32. Student result = aggregate.getUniqueMappedResult();
    33. Console.log(JSONUtil.toJsonPrettyStr(result));
    34. }
  2. 验证

控制台输入如图,多表联查成功
image.png