2020年7月31日更,以下方法太麻烦,请移步,我经过测试,发现该博主的方法在我这边需要先createIndex后putMapping,否则会报错。此外,定义的实体类中必须含有@Id定义的id属性,否则也会报错。
但是以上方法仍然是有短板的,因为根据@Field来定义数据类型时,是只有String, Integer, Long, Date, Float, Double, Boolean, Object, Auto, Nested, Ip, Attachment这几个类型可以定义,无法定义byte和short(代码里FieldType枚举类中就没定义这俩),所以即使是一个很小的数字也必须使用Integer来装(而使用@Mapping标签时用的配置文件可以定义byte)。网上很多都有说在满足需求的情况下,尽可能选择范围小的数据类型。我经过测试,发现同样的数据,使用byte所占存储空间明显比Integer或Long要小,至于查询效率会不会被影响,我没测过。所以使用@Field还是@Mapping这就要看自己的具体需要了。
-------------------------------------------------
elasticsearch2.4版本,使用spring-data-elasticsearch-2.1.23.RELEASE.jar来操作,发现实体类的Field标签定义的内容无效。查阅多方资料说是spring-data-elasticsearch根本没有使用该标签。按网上的解决方法是使用mappingPath标签,如下:
@Document(indexName = "#{index.indexName}", type = "txt", replicas = 0, shards = 1)
@Mapping(mappingPath = "es-logXXXXXX.json")
public class LogEntity {
private String name;
private int day;
private int num;
private String text;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getDay() {
return day;
}
public void setDay(int day) {
this.day = day;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
Document里indexName的写法是我动态设置bean来实现动态index名称,与本问题无关。在项目src路径下建立一个文件es-logXXXXXX.json,如下:
{
"properties": {
"num": {
"type": "long"
},
"name": {
"type": "string",
"index": "not_analyzed"
},
"text": {
"type": "string",
"analyzer": "whitespace"
},
"day": {
"type": "long"
}
}
}
这样设置后新创建的index还是无效,与网上教程没有区别啊,是否与我使用的是ElasticsearchTemplate有关呢?
总之就是,在我的代码中还缺少了一步,就是要加上elasticsearchTemplate.putMapping(LogEntity.class);这句代码。
第一步,以上俩文件齐全后,调用
elasticsearchTemplate.createIndex(LogEntity.class);
创建index后,索引信息如下,可以看到mappings属性是空的,没有任何我在es-logXXXXXX.json里定义的内容。
{
"state": "open",
"settings": {
"index": {
"refresh_interval": "1s",
"number_of_shards": "1",
"creation_date": "1587014790803",
"store": {
"type": "fs"
},
"number_of_replicas": "0",
"uuid": "FKHOqrlySGS6o4609ot6DA",
"version": {
"created": "2040699"
}
}
},
"mappings": {
},
"aliases": []
}
第二步,在插入数据之前,调用(也是我上边说的少的那步)
elasticsearchTemplate.putMapping(LogEntity.class);
最后插入数据,索引信息会变为如下这样
{
"state": "open",
"settings": {
"index": {
"refresh_interval": "1s",
"number_of_shards": "1",
"creation_date": "1587535172761",
"store": {
"type": "fs"
},
"number_of_replicas": "0",
"uuid": "HMA_0C_YTuiYrA0fKf42vQ",
"version": {
"created": "2040699"
}
}
},
"mappings": {
"txt": {
"properties": {
"num": {
"type": "long"
},
"name": {
"index": "not_analyzed",
"type": "string"
},
"text": {
"analyzer": "whitespace",
"type": "string"
},
"day": {
"type": "long"
}
}
}
},
"aliases": []
}
可以看到,mappings里有了属性值,用查询数据来验证分词器和是否分词都已生效。
如果在插入数据之前没有使用elasticsearchTemplate.putMapping(LogEntity.class);,那么mappings里会生成默认的值,而不会使用我的配置。