动态索引支持
# 动态索引
尽管我们的每个mapper已经可以决定当前CRUD作用的索引,用户根据不同的mapper就可以操作到不同的索引,这点和MP中不同mapper对应不同的表是一样的. 但是在ES中有一种场景,需要动态索引.例如某公司日志存放在ES中,但日志量极其庞大,并且使用方通常也只关注近三个月内的日志,因此按照年或者月建立索引, 不仅可以提升查询速度和性能,而且可以更好的归类数据.但是EE中的索引是通过@IndexName注解写在代码中的,这就导致用户在想切换索引时还需要重新改代码 并重启项目,这显然不是一个好的解决方案,因此我们额外提供了对动态索引的支持.
- 方式1 直接设置当前mapper对应的索引名 简单粗暴
@Test
public void testActiveIndex(){
// 设置当前mapper对应的索引 比如原索引名叫document, 设置以后 documentMapper对应的所有CRUD作用的索引将变更为指定的索引名,例如 '2023-03-11'
String indexName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
documentMapper.setCurrentActiveIndex(indexName);
}
1
2
3
4
5
6
2
3
4
5
6
提示
此方案虽然简单粗暴又省事,但有两个细节需要注意:
- 不支持分布式环境,因为每个mapper作用的索引是存在jvm缓存中,当前设置操作仅能作用于当前机器,如果要支持分布式环境,则需要用户对每台机器都执行此方法
- 不保证原子性,该操作在执行索引变更时若有其它线程在执行数据的CRUD,并不会阻塞其它线程执行CRUD,因此在高并发场景下,无法保证原子性.
- 方式2 通过wrapper或mapper中具体的方法传入索引名 粒度最细
@Test
public void testSelect() {
// 支持设置多个查询的索引,用逗号隔开即可
LambdaEsQueryWrapper<Document> wrapper = new LambdaEsQueryWrapper<>();
wrapper.eq(Document::getTitle, "老汉")
.index("你要查询的索引名1","你想查询的索引名2");
Document document = documentMapper.selectOne(wrapper);
System.out.println(document);
}
@Test
public void testInsert() {
// 像插入,更新等一些没有wrapper的情况,在mapper中都有提供方法重载,可以直接传入索引名
Document document = new Document();
document.setEsId("5");
document.setTitle("老汉");
// 支持设置多个查询的索引,用逗号隔开即可
int successCount = documentMapper.insert(document,"你想插入的索引名1","你想插入的索引名2");
Assertions.assertEquals(successCount, 1);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 落地方案
前面章节我们介绍了手动挡创建索引的API,配合此处提供的索引激活方案就可以轻而易举实现动态索引了
@Test
public void testCreateIndexByEntity() {
// 适用于定时任务按日期创建索引场景
String indexName = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
documentMapper.createIndex(indexName);
}
1
2
3
4
5
6
2
3
4
5
6
1.写定时任务调用创建索引API创建索引,索引名以你想要的日期格式进行生成并将索引名置入redis缓存
2.生成完成后,全局设置当前mapper对应索引名为redis中存入的最新索引名 或者在CRUD时从redis去取最新索引名
当然上面仅是提供一种可行的参考方案,用户还可以根据API提供的能力结合自己项目的特性去设计个性化解决方案.
帮助我们改善此文档 (opens new window)
上次更新: 2024/05/18