1.查询索引

  1. List<IndexInfo> indexInfo = mongoTemplate.indexOps(Student.class).getIndexInfo();

2.删除索引

  1. mongoTemplate.indexOps(Student.class).dropIndex("age_1");
  2. mongoTemplate.indexOps(Student.class).dropAllIndexes();

3.创建索引

单列索引、复合索引、多键值索引

全文索引,hash索引,地理位置索引(2d或2dSphere)目前只支持注解,但是不知道为什么我测试没有生效。个人还是更习惯直接命令行创建索引

  1. @Test
  2. void testCreateIndex() {
  3. //1.创建单列索引
  4. Index index = new Index().on("age", Sort.Direction.ASC);
  5. String indexName = mongoTemplate.indexOps(Student.class).ensureIndex(index);
  6. Console.log(indexName);
  7. //2.创建复合索引
  8. Index compoundIndex = new Index().on("name", Sort.Direction.ASC).on("age", Sort.Direction.ASC);
  9. indexName = mongoTemplate.indexOps(Student.class).ensureIndex(compoundIndex);
  10. Console.log(indexName);
  11. //3.创建多键值索引(tags列为字符串数组)
  12. Index multiKeyValueIndex = new Index().on("tags", Sort.Direction.DESC);
  13. indexName = mongoTemplate.indexOps(Student.class).ensureIndex(multiKeyValueIndex);
  14. Console.log(indexName);
  15. }

4.使用索引查询

单列索引,复合索引,多键值索引,hash索引

常规find()查询即可

全文索引

与命令相同,包括find查询以及aggregate查询两种
使用TextCriteria来封装查询条件

  1. //1.find查询
  2. List<Student> students = mongoTemplate.find(new Query(TextCriteria.forDefaultLanguage().matching("1")), Student.class);
  3. Assert.isTrue(1 == students.size());
  4. Assert.isTrue("1".equals(students.get(0).getId()));
  5. //2.聚合查询
  6. MatchOperation matchOperation = Aggregation.match(new TextCriteria().forDefaultLanguage().matching("1"));
  7. TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, matchOperation);
  8. AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);
  9. Student result = aggregate.getUniqueMappedResult();
  10. Assert.isTrue("1".equals(result.getId()));

地理位置索引数据点示例

:::info 定义四个数据点(北京、大同、太原、湖南)
以北京为圆心

  1. 北京距离大同约等于300km
  2. 北京距离太原约等于500km
  3. 北京距离湖南约等于1750km :::

    2d平面-地理位置索引

    实体类

    ```java import lombok.Data; import org.springframework.data.mongodb.core.index.CompoundIndex; import org.springframework.data.mongodb.core.index.CompoundIndexes; import org.springframework.data.mongodb.core.mapping.Document;

/**

  • @author 冯铁城 [17615007230@163.com]
  • @date 2022-07-25 20:18:40
  • @describe: */ @Data @Document(collection = “geo”) public class Flat {

    private String id;

    private String name;

    private double[] loc; }

    1. <a name="rL6Yg"></a>
    2. #### find查询
    3. find查询可以不指定maxDistance的单位。平面maxDistance默认单位为1度,1度约等于111km
    4. ```java
    5. @Test
    6. void testSelect() {
    7. //1.定义平面坐标点
    8. List<Flat> flats = CollUtil.newArrayList();
    9. Flat flat = new Flat();
    10. flat.setName("北京");
    11. flat.setLoc(new double[]{115.25, 39.26});
    12. flats.add(flat);
    13. flat = new Flat();
    14. flat.setName("大同");
    15. flat.setLoc(new double[]{112.34, 39.03});
    16. flats.add(flat);
    17. flat = new Flat();
    18. flat.setName("太原");
    19. flat.setLoc(new double[]{111.3, 37.27});
    20. flats.add(flat);
    21. flat = new Flat();
    22. flat.setName("湖南");
    23. flat.setLoc(new double[]{108.47, 24.38});
    24. flats.add(flat);
    25. mongoTemplate.insert(flats, Flat.class);
    26. //3.全量查询,无最大距离
    27. Point point = new Point(115.28, 39.23);
    28. List<Flat> result = mongoTemplate.find(new Query(Criteria.where("loc").near(point)), Flat.class);
    29. Assert.isTrue(4 == result.size());
    30. //3.非全量查询,有最大距离
    31. point = new Point(115.28, 39.23);
    32. result = mongoTemplate.find(new Query(Criteria.where("loc").near(point).maxDistance(3)), Flat.class);
    33. Assert.isTrue(2 == result.size());
    34. }

    geoNear查询

    geoNear的优点是可以返回点之间的距离,也可以通过Metrics来指定maxDistance单位,如果不指定,默认单位为1度,约等于111km
    geoNear返回的distance默认单位为km

    1. @Test
    2. void testSelect() {
    3. //1.定义平面坐标点
    4. List<Flat> flats = CollUtil.newArrayList();
    5. Flat flat = new Flat();
    6. flat.setName("北京");
    7. flat.setLoc(new double[]{115.25, 39.26});
    8. flats.add(flat);
    9. flat = new Flat();
    10. flat.setName("大同");
    11. flat.setLoc(new double[]{112.34, 39.03});
    12. flats.add(flat);
    13. flat = new Flat();
    14. flat.setName("太原");
    15. flat.setLoc(new double[]{111.3, 37.27});
    16. flats.add(flat);
    17. flat = new Flat();
    18. flat.setName("湖南");
    19. flat.setLoc(new double[]{108.47, 24.38});
    20. flats.add(flat);
    21. mongoTemplate.insert(flats, Flat.class);
    22. //2.定义圆心点
    23. Point point = new Point(115.28, 39.23);
    24. //3.全量查询,无最大距离
    25. NearQuery nearQuery = NearQuery.near(point);
    26. GeoResults<Flat> geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
    27. List<GeoResult<Flat>> content = geoResults.getContent();
    28. Assert.isTrue(4 == content.size());
    29. //4.非全量查询,有最大距离
    30. nearQuery = NearQuery.near(point).maxDistance(300, Metrics.KILOMETERS);
    31. geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
    32. content = geoResults.getContent();
    33. Assert.isTrue(2 == content.size());
    34. }

    2dsphere球面-地理位置索引

    实体类

    球面索引的坐标点,建议用GeoJsonPoint来映射。因为2dsphere索引的列,值得类型允许经纬度数据或geoJson类型。建议使用geoJson类型 ```java import lombok.Data; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.mapping.Document;

/**

  • @author 冯铁城 [17615007230@163.com]
  • @date 2022-07-25 20:18:40
  • @describe: */ @Data @Document(collection = “geo”) public class Flat {

    private String id;

    private String name;

    private GeoJsonPoint point; }

    1. <a name="kgcOr"></a>
    2. #### find查询
    3. nearSphere可以进行球面查询,缺点是不能返回点之间的距离。球面索引默认maxDistance单位为1m
    4. ```java
    5. @Test
    6. void testSelect() {
    7. //1.定义平面坐标点
    8. List<Flat> flats = CollUtil.newArrayList();
    9. Flat flat = new Flat();
    10. flat.setName("北京");
    11. flat.setPoint(new GeoJsonPoint(115.25, 39.26));
    12. flats.add(flat);
    13. flat = new Flat();
    14. flat.setName("大同");
    15. flat.setPoint(new GeoJsonPoint(112.34, 39.03));
    16. flats.add(flat);
    17. flat = new Flat();
    18. flat.setName("太原");
    19. flat.setPoint(new GeoJsonPoint(111.3, 37.27));
    20. flats.add(flat);
    21. flat = new Flat();
    22. flat.setName("湖南");
    23. flat.setPoint(new GeoJsonPoint(108.47, 24.38));
    24. flats.add(flat);
    25. mongoTemplate.insert(flats, Flat.class);
    26. //2.定义圆心点
    27. GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
    28. //3.全量查询,无最大距离
    29. List<Flat> result = mongoTemplate.find(new Query(Criteria.where("point").nearSphere(point)), Flat.class);
    30. Assert.isTrue(4 == result.size());
    31. //4.非全量查询,有最大距离
    32. result = mongoTemplate.find(new Query(Criteria.where("point").nearSphere(point).maxDistance(300000)), Flat.class);
    33. Assert.isTrue(2 == result.size());
    34. }

    geoNear查询

    geoNear的优点是可以返回点之间的距离,也可以通过Metrics来指定maxDistance单位,如果不指定,默认单位为1m
    geoNear返回的distance默认单位为km

    1. @Test
    2. void testSelect() {
    3. //1.定义平面坐标点
    4. List<Flat> flats = CollUtil.newArrayList();
    5. Flat flat = new Flat();
    6. flat.setName("北京");
    7. flat.setPoint(new GeoJsonPoint(115.25, 39.26));
    8. flats.add(flat);
    9. flat = new Flat();
    10. flat.setName("大同");
    11. flat.setPoint(new GeoJsonPoint(112.34, 39.03));
    12. flats.add(flat);
    13. flat = new Flat();
    14. flat.setName("太原");
    15. flat.setPoint(new GeoJsonPoint(111.3, 37.27));
    16. flats.add(flat);
    17. flat = new Flat();
    18. flat.setName("湖南");
    19. flat.setPoint(new GeoJsonPoint(108.47, 24.38));
    20. flats.add(flat);
    21. mongoTemplate.insert(flats, Flat.class);
    22. //2.定义圆心点
    23. GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
    24. //3.全量查询,无最大距离
    25. NearQuery nearQuery = NearQuery.near(point);
    26. GeoResults<Flat> geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
    27. List<GeoResult<Flat>> content = geoResults.getContent();
    28. Assert.isTrue(4 == content.size());
    29. //4.非全量查询,有最大距离
    30. nearQuery = NearQuery.near(point).maxDistance(1800, Metrics.KILOMETERS);
    31. geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
    32. content = geoResults.getContent();
    33. Assert.isTrue(4 == content.size());
    34. //5.指定查询两点之间距离
    35. nearQuery = NearQuery.near(point).maxDistance(1800, Metrics.KILOMETERS)
    36. .query(new Query(Criteria.where("name").is("湖南")));
    37. geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
    38. content = geoResults.getContent();
    39. Assert.isTrue(1 == content.size());
    40. Assert.isTrue("湖南".equals(content.get(0).getContent().getName()));
    41. System.out.println("北京到湖南之间的距离:" + content.get(0).getDistance().getValue());
    42. }

    image.png

    在规定球形范围内查询

    1. @Test
    2. void testSelect() {
    3. //1.定义平面坐标点
    4. List<Flat> flats = CollUtil.newArrayList();
    5. Flat flat = new Flat();
    6. flat.setName("北京");
    7. flat.setPoint(new GeoJsonPoint(115.25, 39.26));
    8. flats.add(flat);
    9. flat = new Flat();
    10. flat.setName("大同");
    11. flat.setPoint(new GeoJsonPoint(112.34, 39.03));
    12. flats.add(flat);
    13. flat = new Flat();
    14. flat.setName("太原");
    15. flat.setPoint(new GeoJsonPoint(111.3, 37.27));
    16. flats.add(flat);
    17. flat = new Flat();
    18. flat.setName("湖南");
    19. flat.setPoint(new GeoJsonPoint(108.47, 24.38));
    20. flats.add(flat);
    21. mongoTemplate.insert(flats, Flat.class);
    22. //2.定义圆心点
    23. GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
    24. //3.定义半径
    25. Distance distance = new Distance(300, Metrics.KILOMETERS);
    26. //4.绘制原型
    27. Circle circle = new Circle(point, distance);
    28. //5.查询
    29. List<Flat> results = mongoTemplate.find(new Query(Criteria.where("point").withinSphere(circle)), Flat.class);
    30. Assert.isTrue(2 == results.size());
    31. }

    5.索引的特性

    实体类

    ```java import lombok.Data; import org.springframework.data.mongodb.core.mapping.Document;

import java.util.Date;

/**

  • @author 冯铁城 [17615007230@163.com]
  • @date 2022-07-20 19:12:01
  • @describe: MongoDB实体类
  • “@Document(collection = “student”)” 用于指定对应哪个集合 */ @Data @Document(collection = “student”) public class Student {

    /**

    • 主键ID */ private Integer id;

      /**

    • 学号 */ private String sno;

      /**

    • 名称 */ private String name;

      /**

    • 年龄 */ private Integer age;

      /**

    • 昵称 */ private String nikeName;

      /**

    • 描述 */ private String des;

      /**

    • 创建时间 */ private Date createTime; }

      1. <a name="sQIln"></a>
      2. ### 集合已创建
      3. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/28218714/1658901352627-644063f3-f953-4179-90a5-7e82616b510f.png#clientId=u93f7c3a1-7489-4&crop=0&crop=0&crop=1&crop=1&errorMessage=unknown%20error&from=paste&height=49&id=ua06b33f3&margin=%5Bobject%20Object%5D&name=image.png&originHeight=73&originWidth=393&originalType=binary&ratio=1&rotation=0&showTitle=false&size=3745&status=error&style=none&taskId=u940986e5-0f2b-47c0-be2b-52820f1fe49&title=&width=262)
      4. <a name="qIihB"></a>
      5. ### 唯一性设置并验证
      6. 学号:unique唯一性
      7. ```java
      8. @Test
      9. void testUnique() {
      10. //1.创建学号唯一索引
      11. Index snoIndex = new Index().on("sno", Sort.Direction.ASC).unique();
      12. mongoTemplate.indexOps(Student.class).ensureIndex(snoIndex);
      13. //2.保存数据
      14. Student student = new Student();
      15. student.setId(1);
      16. student.setSno("1");
      17. mongoTemplate.insert(student);
      18. //3.再次保存数据
      19. student = new Student();
      20. student.setId(2);
      21. student.setSno("1");
      22. try{
      23. mongoTemplate.insert(student);
      24. }catch (Exception e){
      25. Assert.isTrue(e.getMessage().contains("java_test.student index: sno_1 dup key: { sno: \"1\" }"));
      26. }
      27. }

      稀疏性设置并验证

      昵称:sparse稀疏性

      1. @Test
      2. void testSparse() {
      3. //1.创建昵称唯一索引
      4. Index nikeNameIndex = new Index().on("nikeName", Sort.Direction.ASC).unique();
      5. String indexName = mongoTemplate.indexOps(Student.class).ensureIndex(nikeNameIndex);
      6. //2.保存数据
      7. Student student = new Student();
      8. student.setId(1);
      9. student.setNikeName("xxx1");
      10. mongoTemplate.insert(student);
      11. //3.保存1条不包含昵称的数据
      12. student = new Student();
      13. student.setId(2);
      14. mongoTemplate.insert(student);
      15. //4.再次保存1条不包含昵称的数据
      16. student = new Student();
      17. student.setId(3);
      18. try {
      19. mongoTemplate.insert(student);
      20. } catch (Exception e) {
      21. Assert.isTrue(e.getMessage().contains("nikeName_1 dup key: { nikeName: null }"));
      22. }
      23. //5.重新创建索引设置唯一性和稀疏性
      24. mongoTemplate.indexOps(Student.class).dropIndex(indexName);
      25. nikeNameIndex = new Index().on("nikeName", Sort.Direction.ASC).unique().sparse();
      26. mongoTemplate.indexOps(Student.class).ensureIndex(nikeNameIndex);
      27. //6.再次保存2条不包含昵称的数据,无异常抛出
      28. student = new Student();
      29. student.setId(3);
      30. mongoTemplate.insert(student);
      31. student = new Student();
      32. student.setId(4);
      33. mongoTemplate.insert(student);
      34. }

      部分性设置并验证

      年龄:partial部分性

      1. @Test
      2. void testPartial() {
      3. //1.设置索引
      4. Index ageIndex = new Index().on("age", Sort.Direction.ASC)
      5. .partial(PartialIndexFilter.of(Criteria.where("age").gt(6)));
      6. //2.创建索引
      7. mongoTemplate.indexOps(Student.class).ensureIndex(ageIndex);
      8. }

      具体代码怎么验证暂时没想到,从命令行查询,如图,age字段部分索引创建成功
      image.png

      TTL性设置并验证

      1. @Test
      2. void testTtl() {
      3. //1.设置ttl索引
      4. Index createTimeIndex = new Index().on("createTime", Sort.Direction.ASC).expire(10, TimeUnit.SECONDS);
      5. mongoTemplate.indexOps(Student.class).ensureIndex(createTimeIndex);
      6. //2.存入数据
      7. Student student = new Student();
      8. student.setId(1);
      9. student.setCreateTime(new Date());
      10. //3.沉睡10s钟
      11. try {
      12. TimeUnit.SECONDS.sleep(10);
      13. } catch (InterruptedException e) {
      14. throw new RuntimeException(e);
      15. }
      16. //4.再次查询
      17. Student result = mongoTemplate.findOne(new Query(), Student.class);
      18. Assert.isNull(result);
      19. }