【问题标题】:Spring Data Elasticsearch's @Field annotation not workingSpring Data Elasticsearch 的 @Field 注释不起作用
【发布时间】:2015-06-12 07:33:41
【问题描述】:

我在 pom.xml 中有一个带有 Spring Data Elasticsearch 插件的 Spring Boot 应用程序。我创建了一个我想索引的文档类:

@Document(indexName = "operations", type = "operation")
public class OperationDocument {

@Id
private Long id;

@Field(
    type = FieldType.String, 
    index = FieldIndex.analyzed, 
    searchAnalyzer = "standard", 
    indexAnalyzer = "standard",
    store = true
)
private String operationName;

@Field(
    type = FieldType.Date, 
    index = FieldIndex.not_analyzed, 
    store = true, 
    format = DateFormat.custom, pattern = "dd.MM.yyyy hh:mm"
)
private Date dateUp;

@Field(
    type = FieldType.String, 
    index = FieldIndex.not_analyzed, 
    store = false
) 
private String someTransientData;

@Field(type = FieldType.Nested)
private List<Sector> sectors;

//Getter and setters

我还为这个类创建了一个存储库:

 public interface OperationDocumentRepository 
      extends ElasticsearchRepository<OperationDocument, Long> {
 }

我做了一个测试,使用存储库索引三个示例对象。它很长,所以我会发布它只需要。事实上,在 ES 服务器中创建的映射忽略了 @Field 注解设置的配置:

"mappings": {
  "operation": {
    "properties": {
      "operationName": {
        "type": "string"
      },
      "dateUp": {
        "type": "long"
      },
      "someTransientData": {
        "type": "string"
      },
      "sectors": {
        "properties": {
          "id": {
            "type": "long"
          },
          "sectorName": {
            "type": "string"
          }
        }
      }
    }
  }
}

没有关于分析器的信息,“someTransientData”被存储和索引,dateUp 被键入为 Long 而不是 Date。

直接从服务器请求的示例文档:

 {
   "_index": "operations",
   "_type": "operation",
   "_id": "AUyUk2cY3nXeOFxdOlQW",
   "_version": 1,
   "_score": 1,
   "_source": {
     "id": null,
     "operationName": "Second Operation Name",
     "dateUp": 1428421827091,
     "someTransientData": "Do not index or store",
     "sectors": [
       {
         "id": 2,
         "sectorName": "Health Care"
       },
       {
         "id": 3,
         "sectorName": "Construction"
       }
     ]
   }
 }

我还注意到,当我第二次运行应用程序时,在启动时出现此错误,仅在索引已存在时打印:

ERROR 19452 --- [main] .dersAbstractElasticsearchRepository : 无法加载 elasticsearch 节点 : org.elasticsearch.index.mapper.MergeMappingException: Merge failed with failures {[mapper [someTransientData] has different index values, mapper [someTransientData]具有不同的tokenize值,mapper [someTransientData]具有不同的index_analyzer,对象映射[sectors]不能从非嵌套更改为嵌套,mapper [operationName]具有不同的存储值,mapper [operationName]具有不同的index_analyzer,mapper [dateUp ] 不同类型,current_type [long],merged_type [date]]}

这是 Spring Data Elastic Search 的错误还是我做错了什么?

我尝试了 spring boot 提供的稳定版本和 spring-data-elasticsearch 的最后一个快照。我还尝试了插件提供的嵌入式 Elasticsearch 服务器和当前版本的外部服务器。我总是得到相同的结果。

【问题讨论】:

    标签: elasticsearch spring-data spring-data-elasticsearch


    【解决方案1】:

    我尝试使用 spring data elasticsearch 示例应用程序复制问题,但根据您的配置,我得到了如上所述的所需结果。

    整个代码都提交到项目这里 --> link

    查看加载spring上下文时生成索引并应用映射的TestCase--> link

    这是由 TestCase 生成的映射:

      {
      "operations" : {
        "aliases" : { },
        "mappings" : {
          "operation" : {
            "properties" : {
              "dateUp" : {
                "type" : "date",
                "store" : true,
                "format" : "dd.MM.yyyy hh:mm"
              },
              "operationName" : {
                "type" : "string",
                "store" : true,
                "analyzer" : "standard"
              },
              "sectors" : {
                "type" : "nested"
              },
              "someTransientData" : {
                "type" : "string",
                "index" : "not_analyzed"
              }
            }
          }
        },
        "settings" : {
          "index" : {
            "refresh_interval" : "1s",
            "number_of_shards" : "5",
            "store" : {
              "type" : "fs"
            },
            "creation_date" : "1428677234773",
            "number_of_replicas" : "1",
            "version" : {
              "created" : "1040499"
            },
            "uuid" : "-djzLu-IQ0CBs-M6R0-R6Q"
          }
        },
        "warmers" : { }
      }
    }
    

    你能用https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-data-elasticsearch创建类似的spring boot例子吗

    并提交公共共享?

    【讨论】:

    • 我测试了您的示例并且它有效。然后我创建了一个新的 Spring Boot 项目,它也可以工作。现在我想弄清楚是什么破坏了我的第一个应用程序。如果我找到它,我会更新第一篇文章。谢谢!
    • 我终于可以复制并解决问题了。我在另一个答案中发布了原因和解决方案。
    【解决方案2】:

    我终于可以复制并解决问题了。事实是我使用 ElasticTemplate 来索引和搜索文档而不是存储库,因为我的业务逻辑变得更加复杂(使用聚合等)。

    之后,我删除了未使用的 OperationDocumentRespository。在启动时发布到 ES 服务器的类型映射似乎需要存储库。我认为拥有 @Document 类就足够了,但事实并非如此。

    所以我们在这里有两个选择:

    • 保留 OperationDocumentRepository
    • 将此行添加到应用启动:

      elasticsearchTemplate.putMapping(OperationDocument.class);
      

    【讨论】:

    • 我正在使用 SpringBoot - SpringData Elasticsearch v4.0.3 == ElasticSearch 7.6.2。面对同样的问题@Field 没有帮助。我使用 'IndexOperations indexOps = elasticsearchTemplate.indexOps(Index.class); 创建了索引indexOps.create();'
    【解决方案3】:

    我在使用 spring-data-elasticsearch 时也遇到了这个错误并得到了解决方案。只需在下面输入代码,请检查 cmets。 ES 禁止在创建索引后更改字段类型。但是,您可以更改其他属性,例如 fielddata

    • Spring Data Elasticsearch 3.2.x
    • 弹性搜索 6.8.4
    • Spring Boot 2.2.x
    
    package com.xxxx.xx.es.entity;
    
    import lombok.Builder;
    import lombok.Data;
    import lombok.EqualsAndHashCode;
    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.Mapping;
    
    @EqualsAndHashCode(callSuper = true)
    @Data
    @Builder
    @Document(indexName = "gaming-laptop", indexStoreType = "fs")
    @Mapping(mappingPath = "/gaming-laptop-mappings.json")   // use custom json to configure data structure in ES, default spring data won't work although using @Field(type = FieldType.Keyword)
    public class GamingLaptop extends BaseEntity {
    
        @Id
        private String id;
    
        @Field
        private String cpu;
    
        @Field(type = FieldType.Keyword)  // this only works in ES 7.6.2+, Spring Data Elasticsearch 4.0.X+
        private String brandName;
    
        @Field
        private Integer cores;
    
        @Field
        private Integer threads;
    
        @Field
        private String coreFrequency;
    
        @Field
        private String ssd;
    
        @Field
        private String ram;
    
        @Field
        private String produceDate;
    
        @Field
        private Integer version;
    
        @Field
        private Double price;
    
        @Field(type = FieldType.Keyword)
        private String description;
    
    }
    

    资源/gaming-laptop-mappings.json

    {
        "properties":{
            "_class":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "brandName":{
                "type":"keyword"
            },
            "coreFrequency":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "cores":{
                "type":"long"
            },
            "cpu":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "description":{
                "type":"keyword"
            },
            "gmtCreated":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "gmtModified":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "price":{
                "type":"float"
            },
            "produceDate":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "ram":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "ssd":{
                "type":"text",
                "fields":{
                    "keyword":{
                        "type":"keyword",
                        "ignore_above":256
                    }
                }
            },
            "threads":{
                "type":"long"
            },
            "version":{
                "type":"long"
            }
        }
    }
    

    或者,您可以通过使用 rest 高级客户端来适应 Javier Alvarez 的方法: elasticsearchTemplate.putMapping(OperationDocument.class);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 2013-12-27
      • 2017-10-29
      • 2019-11-09
      • 2021-03-26
      • 1970-01-01
      相关资源
      最近更新 更多