spring - 为我的 spring 项目的不同部署生成不同的 Elasticsearch 映射
问题描述
在我的 spring 项目中,我使用注解来定义 elasticsearch 字段。据我了解,弹性搜索映射是在应用程序启动时基于这些注释生成的。但是,对于不同的部署,生成的映射是不同的。
我正在使用 Java 8 和 ElasticSearch 5.5.0 运行 spring 项目。
注释:
@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,正确的注释具有store
类型为 的属性boolean
。SDE既不知道@Column
也不@SortableField
知道,在构建映射时将被忽略。在具有不同设置的索引中多次使用字段的正确方法是使用字段映射(正如您在链接中看到的那样,这已经在 5.5 中了)。这由带有
@MultiField
注释的 SDE 支持。
我使用以下文件运行了一个最小示例:
规范化器.json
{
"index": {
"analysis": {
"normalizer": {
"lowercase": {
"type": "custom",
"char_filter": [],
"filter": [ "lowercase" ]
}
}
}
}
}
人.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 Boot 应用程序会创建以下索引:
{
"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"
}
}
}
}
}
推荐阅读
- java - 按顺序合并数组
- json - 使用修改后的请求正文发送错误的示例响应
- javascript - Sweetalert - 验证不起作用 + 表单未提交
- git - 从 Git 历史记录中删除文件夹内的文件
- github-pages - 将 GitHub Pages 域用于 Netlify 站点
- perl - 我在 Perl 中遇到了电子邮件程序的问题
- ejabberd - 使用 ejabberd 和 converse.js 在 MUC 中获取通知
- python - 如何在不同的间隔上绘制具有不同功能的曲面?
- if-statement - Katalon Studio for Android 中的 if 语句不会变为 else 语句
- javascript - 我们真的必须对 TypeScript 中的所有内容进行 OOP 化吗?