上一篇文章
es 创建动态索引(一) ,通过el表达式 修改 @Document 里 indexName 值,实现 es 动态索引。
https://www.jianshu.com/p/5d170ce6777d
后来使用时候发现如果实体类上有注解@Field
例如
@Field(type = FieldType.Text, analyzer = "ik_max_word")
springboot 启动时候创建的mapping为:
{
"type": "text",
"analyzer": "ik_max_word"
}
而这种动态的方式为创建的mapping为:
{
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
}
不一样,所以就想看看 启动时候是怎么创建的。使用同样的方式创建就可以。
AbstractElasticsearchRepository.java 中,
构造函数初始时候会去判断要不要创建index和mapping
这个值在@Document中,默认值为true

如果要创建就调用 创建index 和 put mapping方法
public AbstractElasticsearchRepository(ElasticsearchEntityInformation<T, ID> metadata,
ElasticsearchOperations elasticsearchOperations) {
this(elasticsearchOperations);
Assert.notNull(metadata, "ElasticsearchEntityInformation must not be null!");
this.entityInformation = metadata;
setEntityClass(this.entityInformation.getJavaType());
try {
if (createIndexAndMapping()) {
createIndex();
putMapping();
}
} catch (ElasticsearchException exception) {
LOGGER.error("failed to load elasticsearch nodes : " + exception.getDetailedMessage());
}
}
private void createIndex() {
elasticsearchOperations.createIndex(getEntityClass());
}
private void putMapping() {
elasticsearchOperations.putMapping(getEntityClass());
}
而创建和映射是调用elasticsearchOperations 的方法实现的
而它的实现类 即是ElasticsearchTemplate
时序图如下:

所以我们可以在保存数据时候,判断索引是否存在,不存在创建和设置mapping
@Test
public void testsave() throws InterruptedException {
for (int i = 0; i < 6 ; i++) {
Thread.sleep(1000*10);
Student student = new Student();
student.setName("name:"+i);
student.setAge(12);
student.setDesc("hello world");
student.setCreatDate(new Date());
student.setArea("xian");
if(!elasticsearchTemplate.indexExists(student.getClass())){
System.out.println("create index at "+DateUtil.now());
elasticsearchTemplate.createIndex(student.getClass());
elasticsearchTemplate.putMapping(student.getClass());
}
System.out.println("save doc at "+DateUtil.now());
studentService.save(student);
System.out.println("-----save-----");
}
}
亲测 ok 了。
而之前的时间粒度为秒 来创建动态索引 太细了。
可能索引创建和mapping ok 了,但是保存时候 到了下一秒,es 自己就会去创建 。
所以为了测试 将时间细分到 分来测试。
@Data
@Document(
indexName = "student-" + "#{ T(com.river.es.entity.Student).dateStr() }",
//indexName = "student",
type = "student",
shards = 2,
replicas = 1, refreshInterval = "-1")
public class Student {
@Id
private String id;
@Field(type = FieldType.Keyword)
private String name;
@Field(type = FieldType.Integer)
private Integer age;
private String desc;
/**
* 采购区域
*/
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String area;
@Field(type = FieldType.Date,
format = DateFormat.custom,
pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'",timezone="GMT+8")
private Date creatDate;
public static String dateStr()
{
String rst ;
rst = DateUtil.now().replace(" ","-");
return rst.substring(0,16);
}
}
测试结果如下,索引 和 mapping都没问题。
{
"student-2019-06-15-14:56": {
"mappings": {
"student": {
"properties": {
"age": {
"type": "integer"
},
"area": {
"type": "text",
"analyzer": "ik_max_word"
},
"creatDate": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"desc": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "keyword"
}
}
}
}
},
"student-2019-06-15-14:55": {
"mappings": {
"student": {
"properties": {
"age": {
"type": "integer"
},
"area": {
"type": "text",
"analyzer": "ik_max_word"
},
"creatDate": {
"type": "date",
"format": "yyyy-MM-dd'T'HH:mm:ss'Z'"
},
"desc": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"name": {
"type": "keyword"
}
}
}
}
}
}
网友评论