Автоматическое создание типа поля

По умолчанию при индексировании документа elastcsearch пытается автоматом сопоставлять данные с типом поля. Но бывают ситуации, когда луче бы он этого и не делал.

Вот пример:

#создаём индекс
PUT my-index/_doc/1
{
  "value": 2
} 
#получаем тип поля 
GET my-index/_mapping
{
  "my-index" : {
    "mappings" : {
      "properties" : {
        "value" : {
        #на тип long
          "type" : "long"
        }
      }
    }
  }
}
PUT my-index/_doc/2
{
  "value": "4"
} 
PUT my-index/_doc/3
{
  "value": 3
} 
PUT my-index/_doc/4
{
  "value": 2.5
} 
GET my-index/_search
{
  "aggs": {
    "NAME": {
      "sum": {
        "field": "value"
      }
    }
  }
}
}
 итоге мы получили 11 потому что 2.5 было преобразовано в long, т.е 2
"aggregations" : {
    "NAME" : {
      "value" : 11.0
    }
  }

Чтобы отключить автоматическое сопоставление создаём поле с corece: false. При этом вы сможете после этого индексировать документы с типом поля только в long, иначе получите ошибку индексации illegal_argument_exception.

PUT  my-index
{
  "mappings": {
    "properties": {
      "value": {
	     "type": "long",
	     "coerce": false
	   }
	 }
  }
}

Нулевое значение в поле

При индексировании документа в значение поля также может попасть и значение Null, которое не приведёт к ошибке и не будет никак влиять, например, на математические операции.

Но если вы хотите менять все нулевые значения на какое-либо другое значение можно воспользоваться null_value.

PUT  my-index
{
  "mappings": {
    "properties": {
      "value": {
	     "type": "long",
	     "null_value": "2"
	   }
	 }
  }
}
PUT my-index/_doc/1
{
  "value": 2
} 

GET my-index/_mapping

PUT my-index/_doc/2
{
  "value": null
} 
 итоге получим 4
GET my-index/_search
{
  "aggs": {
    "NAME": {
      "sum": {
        "field": "value"
      }
    }
  }
}
}

Указание формата поля с датой

Elastcsearch автоматически проверяет поле на формат с датой. Но если вам нужно изменить формат даты ISO вам потребуется собственные сопоставления.

Для использования этой возможности придётся использовать команду format для поля. Важно при этом elstcsearch не будет перестраивать поле, т.е данные должны приходить именно в том формате что вы указали.

PUT my-index
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        #т.е мы говорим что сперва идёт год - месяц - день
        "format": "yyyy-MM-dd"
      },
    }
  }
}

Индексирование с ошибкой :

PUT my-index/_doc/2
{
  "date": "12-01-2020"
} 
#failed to parse date field [12-01-2020] with format [yyyy-MM-dd]

Индексирование без ошибки :

PUT my-index/_doc/2
{
  "date": "2020-12-01",
} 

Также вы можете указать один из следующих форматов ISO.

А что если вы шлёте данные из разных источников и тип даты разный? На самом деле всё просто, format поддерживает указание множественных типов благодаря ||.

PUT my-index
{
  "mappings": {
    "properties": {
      "date": {
        "type":   "date",
        "format": "yyyy-MM-dd||basic_date"
      },
    }
  }
}

Рекомендуемый процесс сопоставления

Если у вас есть пример ваших будущих данных для индекса правильным будет следующий процесс сопоставления:

  1. Вставляете данные во временный index
    PUT temp-index/_doc/1
    {
      "name": "Ivan",
      "surname": "Lazarev",
      "city": "Astana"
    } 
    
  2. Выводите то, что elastcsearch сопоставил автоматически
    GET temp-index/_mapping
    
  3. Копируете вывод в текстовый файл
  4. Редактируете сопоставления так как нужно вам
  5. Создаёте индекс
    PUT  my-index
    {
      "mappings": {
     "properties": {
         "city" : {
           "type" : "text",
           "fields" : {
             "keyword" : {
               "type" : "keyword",
               "ignore_above" : 256
             }
           }
         },
         "name" : {
           "type" : "text"
         },
         "surname" : {
           "type" : "keyword"
         }
      }
      }
    }
    
  6. Удаляете временный индекс