7.2.2 숫자 - long, double ...

이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍니다.

Elasticsearch는 자바에서 기본으로 사용되는 숫자 타입들을 지원합니다. 그리고 half_float, scaled_float 과 같이 Elasticsearch에서만 사용되는 타입들도 있습니다.

  • long : 64비트 정수 (-9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807)

  • integer : 32비트 정수 (-2147483648 ~ 2147483647)

  • short : 16비트 정수 (-32768 ~ 32767)

  • byte : 8비트 정수 (-128 ~ 127)

  • double : 64비트 실수

  • float : 32비트 실수

  • half_float : 16비트 실수

  • scaled_float : 실수형이지만 부동소수점이 아니라 long 형태로 저장하고 옵션으로 소수점 위치를 지정합니다. 통화 (예: $19.99) 같이 소수점 자리가 고정된 값을 표시할 때 유용합니다.

모든 숫자 필드들에 공통적으로 설정 가능한 옵션들은 다음과 같은 것들이 있습니다.

  • "index", "doc_values", "boost" 옵션들은 text, keyword 필드의 옵션들과 동일합니다.

  • "coerce": <true | false> - 디폴트는 true 입니다. 숫자 필드들은 기본적으로 숫자로 이해될 수 있는 값들은 숫자로 변경해서 저장합니다. 예를 들어 integer 필드에 4, "4", 4.5 등을 입력하면 모두 자연수 4로 자동으로 변환되어 저장됩니다. false 로 설정하면 정확한 타입으로 입력되지 않으면 오류가 발생합니다.

  • "null_value" : <숫자값> - 필드값이 입력되지 않거나 null 인 경우 해당 필드의 디폴트 값을 지정합니다.

  • "ignore_malformed" : <true | false> - 디폴트는 false 입니다. 기본적으로 숫자 필드에 숫자가 아닌 문자나 불린 값이 들어오면 Elasticsearch는 오류를 리턴합니다. true로 설정하게 되면 숫자가 아닌 값이 들어와도 도큐먼트를 정상적으로 저장합니다. 하지만 해당 필드의 값은 _source 에만 저장되고 검색이나 집계에는 무시됩니다.

다음은 scaled_float 타입에서만 사용되는 옵션입니다.

  • "scaling_factor" : <10의 배수> - scaled_float 를 사용하려면 필수로 지정해야 하는 옵션입니다. 소수점 몇 자리까지 저장할지를 지정합니다. 12.3456 이라는 값을 저장하는 경우 scaling_factor: 10 으로 설정했으면 실제로는 12.3 이 저장됩니다. scaling_factor : 100 으로 설정했으면 12.34 가 저장됩니다.

"coerce": true 로 인해 "4.5" 가 integer 필드에 정상적으로 저장 되어도 _source 의 값은 그대로 "4.5" 입니다. 하지만 검색 또는 집계는 4로 적용됩니다. null_value 옵션도 마찬가지로 _source 에는 해당 필드가 null 또는 존재하지 않는 것으로 표시되지만 검색, 또는 집계에는 null_value에 해당하는 값으로 적용이 됩니다.

명심하세요. 전처리된 데이터가 아니면 항상 _source의 값은 변경되지 않습니다.

다음과 같이 my_number 인덱스에 number_val 필드를 byte 로 선언 한 뒤 도큐먼트들을 색인 해 보겠습니다. "coerce" 의 기본 값은 true 이지만 확실하게 하기 위해 이 옵션도 같이 지정하였습니다.

my_number 인덱스 선언
PUT my_number
{
  "mappings": {
    "properties": {
      "number_val" : {
        "type": "byte",
        "coerce" : true
      }
    }
  }
}
my_bumber 인덱스에 벌크로 도큐먼트 색인
PUT my_number/_bulk
{ "index" : { "_id": "1" }}
{ "number_val": 3 }
{ "index" : { "_id": "2" }}
{ "number_val": 4.5 }
{ "index" : { "_id": "3" }}
{ "number_val": "5.2" }
{ "index" : { "_id": "4" }}
{ "number_val": 1024 }

먼저 number_val 은 byte 이기 때문에 "_id": "4" 도큐먼트인 1024 값은 색인이 되지 않고 오류가 발생합니다. 이제 range 쿼리를 이용해서 3 보다 크거나 같고 4.2 보다 작은 값을 검색 해 봅니다.

3 이상, 4.2 미만인 값 검색
GET my_number/_search
{
  "query": {
    "range": {
      "number_val": {
        "gte": 3,
        "lt": 4.2
      }
    }
  }
}

분명 4.2 보다 작은 값을 검색했는데 결과에 4.5 값을 가진 "_id": "2" 도큐먼트가 같이 검색이 되었습니다. _source 에는 4.5 로 값이 들어가 있지만 number_val 필드는 byte 이기 때문에 실제로는 4.5 가 아닌 4 가 저장이 되어 있습니다. 따라서 4.2 보다 작은 값으로 검색이 됩니다. 같은 이유로 _source 에는 텍스트 "5.2" 가 있는 "_id": "3" 도큐먼트 역시 실제로는 자연수 5 가 저장이 됩니다.

조금 전 살펴 본 이유로 숫자 필드를 동적으로 생성하는 것은 매우 위험합니다. 다량의 데이터가 색인 될 때 만약에 가장 처음 들어 온 도큐먼트의 숫자 값이 4 와 같은 자연수인 경우 필드는 자동으로 long 타입으로 생성이 됩니다. 이후에 정수가 아닌 5.5 같은 소수점을 포함한 실수가 들어와도 오류가 발생되지 않고 정상적으로 도큐먼트가 저장됩니다. 하지만 실제로는 5.5 가 아닌 정수 5 가 저장되기 때문에 나중에 검색이나 집계에 오류가 발생하게 됩니다.

Last updated