Spring Данные Elasticsearch @Field аннотация не работает

У меня есть приложение загрузки Spring с плагином Spring Data Elasticsearch в файле pom.xml. Я создал класс документа, который хотел бы индексировать:

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

Я также отметил, что, когда я запускаю приложение во второй раз, во время запуска я получаю эту ошибку, только напечатанную, когда индекс уже существует:

ОШИБКА 19452 --- [main].dersAbstractElasticsearchRepository: не удалось загрузить узлы elasticsearch: org.elasticsearch.index.mapper.MergeMappingException: слияние не удалось с ошибками {[mapper [someTransientData] имеет разные значения индекса, mapper [someTransientData] имеет разные значения tokenize, mapper [someTransientData] имеет другой index_analyzer, сопоставление объектов [сектора] не может быть изменено с не вложенного на вложенный, mapper [operationName] имеет разные значения хранилища, mapper [operationName] имеет другой index_analyzer, mapper [dateUp ] другого типа, current_type [long], merged_type [дата]]}

Это ошибка Spring Data Elastic Search или я делаю что-то неправильно?

Я попробовал стабильную версию, предоставленную Spring загрузкой и последним снимком spring -data-elasticsearch. Я также попробовал встроенный сервер Elasticsearch, предоставленный плагином, и внешний из текущей версии. У меня всегда были одни и те же результаты.

Ответ 1

Я мог бы, наконец, реплицировать и решить проблему. Дело в том, что я использовал ElasticTemplate для индексирования и поиска документов вместо репозиториев, потому что моя бизнес-логика усложнилась (использование агрегатов и т.д.).

После этого я удалил неиспользуемый OperationDocumentRespository. Похоже, что репозиторий необходим для сопоставления типов, отправляемого на сервер ES при запуске. Я думал, что класс @Document должен быть достаточным, но это не так.

Итак, у нас есть два варианта:

  • Храните файл OperationDocumentRepository
  • Добавьте эту строку в начало приложения:

    elasticsearchTemplate.putMapping(OperationDocument.class);
    

Ответ 2

Я попытался реплицировать проблему, используя <образец > w760 > образца данных elasticsearch, но в соответствии с вашей конфигурацией я получаю желаемые результаты, как указано выше.

Целый код предназначен для проекта здесь → ссылка

Посмотрите на TestCase, которые генерируют индекс и применяют сопоставление при загрузке контекста spring → ссылка

Вот отображение, сгенерированное 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" : { }
  }
}

Можете ли вы создать аналогичный пример с загрузкой spring, используя https://github.com/spring-projects/spring-boot/tree/master/spring-boot-samples/spring-boot-sample-data-elasticsearch

и зафиксировать общий ресурс?