一、Spring实现ES的自动按月分割索引
直接先上代码
package com.m.kit.message.service;
import com.google.common.base.Preconditions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.data.elasticsearch.core.query.AliasQuery;
import org.springframework.stereotype.Component;
import java.time.Clock;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
*
* @apiNote
* @author 嗯呢某
* @since 2023/8/3 16:25
*/
@Component("esIndexService")
public class EsIndexService {
private static ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
public EsIndexService(ElasticsearchRestTemplate elasticsearchRestTemplate) {
EsIndexService.elasticsearchRestTemplate = elasticsearchRestTemplate;
}
/**
* 手动添加索引并为索引添加别名
*
* @param indexClass 真实索引(实体类的 @{@link Document#createIndex()}不能设置为true
* @param alias 别名
*/
public <T> boolean checkAndSetIndex(Class<T> indexClass, String alias) {
Preconditions.checkNotNull(alias);
IndexOperations indexOps = elasticsearchRestTemplate.indexOps(indexClass);
if (indexOps.exists()) {
return true;
}
indexOps.create();
AliasQuery aliasQuery = new AliasQuery(alias);
return indexOps.addAlias(aliasQuery);
}
/**
* @apiNote 返回以_开头的日期字符
* @author 嗯呢某
* @since 2023/8/3
* @return java.lang.String
*/
public String esIndexDate() {
LocalDate localDate = LocalDate.now(Clock.systemUTC());
return "_" + localDate.format(DateTimeFormatter.ofPattern("yyyy_MM_dd"));
}
/**
* @apiNote 返回以_开头的月份字符
* @author 嗯呢某
* @since 2023/8/3
* @return java.lang.String
*/
public String esIndexMonth() {
LocalDate localDate = LocalDate.now(Clock.systemUTC());
return "_" + localDate.format(DateTimeFormatter.ofPattern("yyyy_MM"));
}
}
实体类
package com.m.kit.message.es.index;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "test#{@esIndexService.esIndexDate()}", createIndex = false, shards = 1, replicas = 0)
public class TestIndex {
private static final long serialVersionUID = 1L;
/**
* id
*/
@Id
private String id;
/**
* 名称
*/
@Field(type = FieldType.Text)
private String name;
}
定时器(每天)
package com.m.kit.message.es.index;
import com.m.kit.message.service.EsIndexService;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
*
* @apiNote
* @author 嗯呢某
* @since 2023/8/3 17:11
*/
@Component
public class TestIndexCreateTask {
@Resource
private EsIndexService esIndexService;
@Scheduled(cron = "2 0 0 * * ?")
public void create() {
System.out.println("================= 执行开始 ================");
boolean test = esIndexService.createIndexWithAlias(TestIndex.class, "test");
System.out.println("================= 执行结束 ================" + test);
}
}
注意:可以在save的方法前进行判断当前的索引是否存在,不存在的就进行添加
二、使用ES的Index Template来进行生成
//创建索引模板
put _template/template_test
{
"index_patterns":["template.*"], //可以通过"template.*"来适配
"order":1, // 模板的权重, 多个模板的时候优先匹配用, 值越大, 权重越高
"settings":{
"number_of_shards":1, // 分片数量, 可以定义其他配置项(是指索引要做多少个分片,只能在创建索引时指定,后期无法修改)
"number_of_replicas":3 // 副本数量, 可以定义其他配置项(是指每个分片有多少个副本,后期可以动态修改)
},
"aliases":{
"alias_1": {} // 索引对应的别名
},
"mappings":{
"date_detection":false,
"numeric_detection":true
// ES 6.0开始只支持一种type, 名称为“_doc”
"_doc": {
"_source": { // 是否保存字段的原始值
"enabled": false
},
"properties": { // 字段的映射
{
"id" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"age" : {
"type" : "integer"
},
"name" : {
"type" : "keyword"
}
}
}
}
}
}
当满足template.*的索引进行插入数据时,不存在索引时会自动新增
post template.2023_8/_doc
{
"id":"123456789",
"age":18,
"name":"jack"
}
查询时可以根据别名(alias_1)查询