针对我的 spring 项目的不同部署生成不同的 Elasticsearch 映射
Elasticsearch mappings generated differently for different deployments for my spring project
在我的spring项目中,我使用注解来定义elasticsearch字段。据我了解,elasticsearch 映射是在应用程序启动时根据这些注释生成的。但是,生成的映射对于不同的部署是不同的。
我是 运行 spring 项目 Java 8 和 ElasticSearch 5.5.0。
注释:
@Size(min = MINIMUM_LENGTH_NAME, max = MAXIMUM_LENGTH_NAME)
@NotNull
@Column(name = "name", nullable = false)
@Field(store = Store.YES)
@Field(name = "name_forSort", normalizer = @Normalizer(definition = "lowercase"))
@SortableField(forField = "name_forSort")
private String name;
名称的预期映射:
{
"mappings": {
"properties": {
"name" : {
"type" : "text",
"store" : true
},
"name_forSort" : {
"type" : "keyword",
"norms" : true,
"normalizer" : "lowercase"
}
}
}
}
有问题的部署的映射:
{
"mappings": {
"properties": {
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name_forSort" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
}
}
}
Elasticsearch 5.5.0 是旧版本,您没有指定您很少使用哪个 Spring Data Elasticsearch(为简洁起见,我将其称为 SDE)版本。我在这个答案中展示的解决方案是使用支持 Elasticsearch 6.8.2 的当前 SDE 3.2.0.RC1 进行测试的,但是正如在 SDE 的源代码中看到的那样,此功能在旧版本中可用并且应该适用于您的版本也是如此。
您的代码存在问题:
您正在混合放在 属性 上的不同注释,但只有第二个 @Field
注释来自 SDE。 @Field(store = Store.YES)
不是来自 SDE,正确的注释具有类型为 boolean
的 store
属性。 @Column
和 @SortableField
都不为 SDE 所知,因此在构建映射时将被忽略。
在具有不同设置的索引中多次使用一个字段的正确方法是 using fields mapping(正如您在 link 中看到的那样,这已经在 5.5 中了)。 SDE 通过 @MultiField
注释支持这一点。
我有 运行 一个包含以下文件的最小示例:
normalizer.json
{
"index": {
"analysis": {
"normalizer": {
"lowercase": {
"type": "custom",
"char_filter": [],
"filter": [ "lowercase" ]
}
}
}
}
}
Person.java
package com.sothawo.springdataelastictest;
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;
import org.springframework.data.elasticsearch.annotations.InnerField;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.annotations.Setting;
@Document(indexName = "person-test")
@Setting(settingPath = "normalizer.json")
public class Person {
@Id private Long id;
@MultiField(mainField = @Field(store = true, type = FieldType.Text),
otherFields = {
@InnerField(suffix = "forSort",
normalizer = "lowercase",
type = FieldType.Keyword)
})
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PersonRepository.java
package com.sothawo.springdataelastictest;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface PersonRepository extends ElasticsearchRepository<Person, Long> {}
使用这些 类 启动 Spring 引导应用程序会创建以下索引:
{
"person-test": {
"aliases": {},
"mappings": {
"person": {
"properties": {
"name": {
"type": "text",
"store": true,
"fields": {
"forSort": {
"type": "keyword",
"normalizer": "lowercase"
}
}
}
}
}
},
"settings": {
"index": {
"number_of_shards": "5",
"provided_name": "person-test",
"creation_date": "1563903601344",
"analysis": {
"normalizer": {
"lowercase": {
"filter": [
"lowercase"
],
"type": "custom",
"char_filter": []
}
}
},
"number_of_replicas": "1",
"uuid": "WhSFtV-xQ8acXxX6R0gLyg",
"version": {
"created": "6070299"
}
}
}
}
}
问题已通过启动一个新的 ES 实例然后重新索引来解决。奇怪的映射似乎是由先前失败的重建索引和损坏的数据引起的。
在我的spring项目中,我使用注解来定义elasticsearch字段。据我了解,elasticsearch 映射是在应用程序启动时根据这些注释生成的。但是,生成的映射对于不同的部署是不同的。
我是 运行 spring 项目 Java 8 和 ElasticSearch 5.5.0。
注释:
@Size(min = MINIMUM_LENGTH_NAME, max = MAXIMUM_LENGTH_NAME)
@NotNull
@Column(name = "name", nullable = false)
@Field(store = Store.YES)
@Field(name = "name_forSort", normalizer = @Normalizer(definition = "lowercase"))
@SortableField(forField = "name_forSort")
private String name;
名称的预期映射:
{
"mappings": {
"properties": {
"name" : {
"type" : "text",
"store" : true
},
"name_forSort" : {
"type" : "keyword",
"norms" : true,
"normalizer" : "lowercase"
}
}
}
}
有问题的部署的映射:
{
"mappings": {
"properties": {
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"name_forSort" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
}
}
}
Elasticsearch 5.5.0 是旧版本,您没有指定您很少使用哪个 Spring Data Elasticsearch(为简洁起见,我将其称为 SDE)版本。我在这个答案中展示的解决方案是使用支持 Elasticsearch 6.8.2 的当前 SDE 3.2.0.RC1 进行测试的,但是正如在 SDE 的源代码中看到的那样,此功能在旧版本中可用并且应该适用于您的版本也是如此。
您的代码存在问题:
您正在混合放在 属性 上的不同注释,但只有第二个
@Field
注释来自 SDE。@Field(store = Store.YES)
不是来自 SDE,正确的注释具有类型为boolean
的store
属性。@Column
和@SortableField
都不为 SDE 所知,因此在构建映射时将被忽略。在具有不同设置的索引中多次使用一个字段的正确方法是 using fields mapping(正如您在 link 中看到的那样,这已经在 5.5 中了)。 SDE 通过
@MultiField
注释支持这一点。
我有 运行 一个包含以下文件的最小示例:
normalizer.json
{
"index": {
"analysis": {
"normalizer": {
"lowercase": {
"type": "custom",
"char_filter": [],
"filter": [ "lowercase" ]
}
}
}
}
}
Person.java
package com.sothawo.springdataelastictest;
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;
import org.springframework.data.elasticsearch.annotations.InnerField;
import org.springframework.data.elasticsearch.annotations.MultiField;
import org.springframework.data.elasticsearch.annotations.Setting;
@Document(indexName = "person-test")
@Setting(settingPath = "normalizer.json")
public class Person {
@Id private Long id;
@MultiField(mainField = @Field(store = true, type = FieldType.Text),
otherFields = {
@InnerField(suffix = "forSort",
normalizer = "lowercase",
type = FieldType.Keyword)
})
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
PersonRepository.java
package com.sothawo.springdataelastictest;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
public interface PersonRepository extends ElasticsearchRepository<Person, Long> {}
使用这些 类 启动 Spring 引导应用程序会创建以下索引:
{
"person-test": {
"aliases": {},
"mappings": {
"person": {
"properties": {
"name": {
"type": "text",
"store": true,
"fields": {
"forSort": {
"type": "keyword",
"normalizer": "lowercase"
}
}
}
}
}
},
"settings": {
"index": {
"number_of_shards": "5",
"provided_name": "person-test",
"creation_date": "1563903601344",
"analysis": {
"normalizer": {
"lowercase": {
"filter": [
"lowercase"
],
"type": "custom",
"char_filter": []
}
}
},
"number_of_replicas": "1",
"uuid": "WhSFtV-xQ8acXxX6R0gLyg",
"version": {
"created": "6070299"
}
}
}
}
}
问题已通过启动一个新的 ES 实例然后重新索引来解决。奇怪的映射似乎是由先前失败的重建索引和损坏的数据引起的。