首页 > 解决方案 > 为我的 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
           }
         }
       },
    }
  }
}

标签: springjava-8elasticsearch-5spring-data-elasticsearchelasticsearch-mapping

解决方案


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"
        }
      }
    }
  }
}

推荐阅读