1.查询索引
List<IndexInfo> indexInfo = mongoTemplate.indexOps(Student.class).getIndexInfo();
2.删除索引
mongoTemplate.indexOps(Student.class).dropIndex("age_1");
mongoTemplate.indexOps(Student.class).dropAllIndexes();
3.创建索引
单列索引、复合索引、多键值索引
全文索引,hash索引,地理位置索引(2d或2dSphere)目前只支持注解,但是不知道为什么我测试没有生效。个人还是更习惯直接命令行创建索引
@Test
void testCreateIndex() {
//1.创建单列索引
Index index = new Index().on("age", Sort.Direction.ASC);
String indexName = mongoTemplate.indexOps(Student.class).ensureIndex(index);
Console.log(indexName);
//2.创建复合索引
Index compoundIndex = new Index().on("name", Sort.Direction.ASC).on("age", Sort.Direction.ASC);
indexName = mongoTemplate.indexOps(Student.class).ensureIndex(compoundIndex);
Console.log(indexName);
//3.创建多键值索引(tags列为字符串数组)
Index multiKeyValueIndex = new Index().on("tags", Sort.Direction.DESC);
indexName = mongoTemplate.indexOps(Student.class).ensureIndex(multiKeyValueIndex);
Console.log(indexName);
}
4.使用索引查询
单列索引,复合索引,多键值索引,hash索引
全文索引
与命令相同,包括find查询以及aggregate查询两种
使用TextCriteria来封装查询条件
//1.find查询
List<Student> students = mongoTemplate.find(new Query(TextCriteria.forDefaultLanguage().matching("1")), Student.class);
Assert.isTrue(1 == students.size());
Assert.isTrue("1".equals(students.get(0).getId()));
//2.聚合查询
MatchOperation matchOperation = Aggregation.match(new TextCriteria().forDefaultLanguage().matching("1"));
TypedAggregation<Student> typedAggregation = Aggregation.newAggregation(Student.class, matchOperation);
AggregationResults<Student> aggregate = mongoTemplate.aggregate(typedAggregation, Student.class);
Student result = aggregate.getUniqueMappedResult();
Assert.isTrue("1".equals(result.getId()));
地理位置索引数据点示例
:::info
定义四个数据点(北京、大同、太原、湖南)
以北京为圆心
- 北京距离大同约等于300km
- 北京距离太原约等于500km
- 北京距离湖南约等于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; }
<a name="rL6Yg"></a>
#### find查询
find查询可以不指定maxDistance的单位。平面maxDistance默认单位为1度,1度约等于111km
```java
@Test
void testSelect() {
//1.定义平面坐标点
List<Flat> flats = CollUtil.newArrayList();
Flat flat = new Flat();
flat.setName("北京");
flat.setLoc(new double[]{115.25, 39.26});
flats.add(flat);
flat = new Flat();
flat.setName("大同");
flat.setLoc(new double[]{112.34, 39.03});
flats.add(flat);
flat = new Flat();
flat.setName("太原");
flat.setLoc(new double[]{111.3, 37.27});
flats.add(flat);
flat = new Flat();
flat.setName("湖南");
flat.setLoc(new double[]{108.47, 24.38});
flats.add(flat);
mongoTemplate.insert(flats, Flat.class);
//3.全量查询,无最大距离
Point point = new Point(115.28, 39.23);
List<Flat> result = mongoTemplate.find(new Query(Criteria.where("loc").near(point)), Flat.class);
Assert.isTrue(4 == result.size());
//3.非全量查询,有最大距离
point = new Point(115.28, 39.23);
result = mongoTemplate.find(new Query(Criteria.where("loc").near(point).maxDistance(3)), Flat.class);
Assert.isTrue(2 == result.size());
}
geoNear查询
geoNear的优点是可以返回点之间的距离,也可以通过Metrics来指定maxDistance单位,如果不指定,默认单位为1度,约等于111km
geoNear返回的distance默认单位为km@Test
void testSelect() {
//1.定义平面坐标点
List<Flat> flats = CollUtil.newArrayList();
Flat flat = new Flat();
flat.setName("北京");
flat.setLoc(new double[]{115.25, 39.26});
flats.add(flat);
flat = new Flat();
flat.setName("大同");
flat.setLoc(new double[]{112.34, 39.03});
flats.add(flat);
flat = new Flat();
flat.setName("太原");
flat.setLoc(new double[]{111.3, 37.27});
flats.add(flat);
flat = new Flat();
flat.setName("湖南");
flat.setLoc(new double[]{108.47, 24.38});
flats.add(flat);
mongoTemplate.insert(flats, Flat.class);
//2.定义圆心点
Point point = new Point(115.28, 39.23);
//3.全量查询,无最大距离
NearQuery nearQuery = NearQuery.near(point);
GeoResults<Flat> geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
List<GeoResult<Flat>> content = geoResults.getContent();
Assert.isTrue(4 == content.size());
//4.非全量查询,有最大距离
nearQuery = NearQuery.near(point).maxDistance(300, Metrics.KILOMETERS);
geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
content = geoResults.getContent();
Assert.isTrue(2 == content.size());
}
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; }
<a name="kgcOr"></a>
#### find查询
nearSphere可以进行球面查询,缺点是不能返回点之间的距离。球面索引默认maxDistance单位为1m
```java
@Test
void testSelect() {
//1.定义平面坐标点
List<Flat> flats = CollUtil.newArrayList();
Flat flat = new Flat();
flat.setName("北京");
flat.setPoint(new GeoJsonPoint(115.25, 39.26));
flats.add(flat);
flat = new Flat();
flat.setName("大同");
flat.setPoint(new GeoJsonPoint(112.34, 39.03));
flats.add(flat);
flat = new Flat();
flat.setName("太原");
flat.setPoint(new GeoJsonPoint(111.3, 37.27));
flats.add(flat);
flat = new Flat();
flat.setName("湖南");
flat.setPoint(new GeoJsonPoint(108.47, 24.38));
flats.add(flat);
mongoTemplate.insert(flats, Flat.class);
//2.定义圆心点
GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
//3.全量查询,无最大距离
List<Flat> result = mongoTemplate.find(new Query(Criteria.where("point").nearSphere(point)), Flat.class);
Assert.isTrue(4 == result.size());
//4.非全量查询,有最大距离
result = mongoTemplate.find(new Query(Criteria.where("point").nearSphere(point).maxDistance(300000)), Flat.class);
Assert.isTrue(2 == result.size());
}
geoNear查询
geoNear的优点是可以返回点之间的距离,也可以通过Metrics来指定maxDistance单位,如果不指定,默认单位为1m
geoNear返回的distance默认单位为km@Test
void testSelect() {
//1.定义平面坐标点
List<Flat> flats = CollUtil.newArrayList();
Flat flat = new Flat();
flat.setName("北京");
flat.setPoint(new GeoJsonPoint(115.25, 39.26));
flats.add(flat);
flat = new Flat();
flat.setName("大同");
flat.setPoint(new GeoJsonPoint(112.34, 39.03));
flats.add(flat);
flat = new Flat();
flat.setName("太原");
flat.setPoint(new GeoJsonPoint(111.3, 37.27));
flats.add(flat);
flat = new Flat();
flat.setName("湖南");
flat.setPoint(new GeoJsonPoint(108.47, 24.38));
flats.add(flat);
mongoTemplate.insert(flats, Flat.class);
//2.定义圆心点
GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
//3.全量查询,无最大距离
NearQuery nearQuery = NearQuery.near(point);
GeoResults<Flat> geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
List<GeoResult<Flat>> content = geoResults.getContent();
Assert.isTrue(4 == content.size());
//4.非全量查询,有最大距离
nearQuery = NearQuery.near(point).maxDistance(1800, Metrics.KILOMETERS);
geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
content = geoResults.getContent();
Assert.isTrue(4 == content.size());
//5.指定查询两点之间距离
nearQuery = NearQuery.near(point).maxDistance(1800, Metrics.KILOMETERS)
.query(new Query(Criteria.where("name").is("湖南")));
geoResults = mongoTemplate.geoNear(nearQuery, Flat.class);
content = geoResults.getContent();
Assert.isTrue(1 == content.size());
Assert.isTrue("湖南".equals(content.get(0).getContent().getName()));
System.out.println("北京到湖南之间的距离:" + content.get(0).getDistance().getValue());
}
在规定球形范围内查询
@Test
void testSelect() {
//1.定义平面坐标点
List<Flat> flats = CollUtil.newArrayList();
Flat flat = new Flat();
flat.setName("北京");
flat.setPoint(new GeoJsonPoint(115.25, 39.26));
flats.add(flat);
flat = new Flat();
flat.setName("大同");
flat.setPoint(new GeoJsonPoint(112.34, 39.03));
flats.add(flat);
flat = new Flat();
flat.setName("太原");
flat.setPoint(new GeoJsonPoint(111.3, 37.27));
flats.add(flat);
flat = new Flat();
flat.setName("湖南");
flat.setPoint(new GeoJsonPoint(108.47, 24.38));
flats.add(flat);
mongoTemplate.insert(flats, Flat.class);
//2.定义圆心点
GeoJsonPoint point = new GeoJsonPoint(115.28, 39.23);
//3.定义半径
Distance distance = new Distance(300, Metrics.KILOMETERS);
//4.绘制原型
Circle circle = new Circle(point, distance);
//5.查询
List<Flat> results = mongoTemplate.find(new Query(Criteria.where("point").withinSphere(circle)), Flat.class);
Assert.isTrue(2 == results.size());
}
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; }
<a name="sQIln"></a>
### 集合已创建
![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)
<a name="qIihB"></a>
### 唯一性设置并验证
学号:unique唯一性
```java
@Test
void testUnique() {
//1.创建学号唯一索引
Index snoIndex = new Index().on("sno", Sort.Direction.ASC).unique();
mongoTemplate.indexOps(Student.class).ensureIndex(snoIndex);
//2.保存数据
Student student = new Student();
student.setId(1);
student.setSno("1");
mongoTemplate.insert(student);
//3.再次保存数据
student = new Student();
student.setId(2);
student.setSno("1");
try{
mongoTemplate.insert(student);
}catch (Exception e){
Assert.isTrue(e.getMessage().contains("java_test.student index: sno_1 dup key: { sno: \"1\" }"));
}
}
稀疏性设置并验证
昵称:sparse稀疏性
@Test
void testSparse() {
//1.创建昵称唯一索引
Index nikeNameIndex = new Index().on("nikeName", Sort.Direction.ASC).unique();
String indexName = mongoTemplate.indexOps(Student.class).ensureIndex(nikeNameIndex);
//2.保存数据
Student student = new Student();
student.setId(1);
student.setNikeName("xxx1");
mongoTemplate.insert(student);
//3.保存1条不包含昵称的数据
student = new Student();
student.setId(2);
mongoTemplate.insert(student);
//4.再次保存1条不包含昵称的数据
student = new Student();
student.setId(3);
try {
mongoTemplate.insert(student);
} catch (Exception e) {
Assert.isTrue(e.getMessage().contains("nikeName_1 dup key: { nikeName: null }"));
}
//5.重新创建索引设置唯一性和稀疏性
mongoTemplate.indexOps(Student.class).dropIndex(indexName);
nikeNameIndex = new Index().on("nikeName", Sort.Direction.ASC).unique().sparse();
mongoTemplate.indexOps(Student.class).ensureIndex(nikeNameIndex);
//6.再次保存2条不包含昵称的数据,无异常抛出
student = new Student();
student.setId(3);
mongoTemplate.insert(student);
student = new Student();
student.setId(4);
mongoTemplate.insert(student);
}
部分性设置并验证
年龄:partial部分性
@Test
void testPartial() {
//1.设置索引
Index ageIndex = new Index().on("age", Sort.Direction.ASC)
.partial(PartialIndexFilter.of(Criteria.where("age").gt(6)));
//2.创建索引
mongoTemplate.indexOps(Student.class).ensureIndex(ageIndex);
}
具体代码怎么验证暂时没想到,从命令行查询,如图,age字段部分索引创建成功
TTL性设置并验证
@Test
void testTtl() {
//1.设置ttl索引
Index createTimeIndex = new Index().on("createTime", Sort.Direction.ASC).expire(10, TimeUnit.SECONDS);
mongoTemplate.indexOps(Student.class).ensureIndex(createTimeIndex);
//2.存入数据
Student student = new Student();
student.setId(1);
student.setCreateTime(new Date());
//3.沉睡10s钟
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
//4.再次查询
Student result = mongoTemplate.findOne(new Query(), Student.class);
Assert.isNull(result);
}