7.2.2 숫자 - long, double ...
이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민([email protected])에게 사용 내용을 알려주시기 바랍니다.
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 인덱스 선언
1
PUT my_number
2
{
3
"mappings": {
4
"properties": {
5
"number_val" : {
6
"type": "byte",
7
"coerce" : true
8
}
9
}
10
}
11
}
Copied!
request
response
my_bumber 인덱스에 벌크로 도큐먼트 색인
1
PUT my_number/_bulk
2
{ "index" : { "_id": "1" }}
3
{ "number_val": 3 }
4
{ "index" : { "_id": "2" }}
5
{ "number_val": 4.5 }
6
{ "index" : { "_id": "3" }}
7
{ "number_val": "5.2" }
8
{ "index" : { "_id": "4" }}
9
{ "number_val": 1024 }
Copied!
my_bumber 인덱스에 벌크로 도큐먼트 색인 결과
1
{
2
"took" : 46,
3
"errors" : true,
4
"items" : [
5
{
6
"index" : {
7
"_index" : "my_number",
8
"_type" : "_doc",
9
"_id" : "1",
10
"_version" : 1,
11
"result" : "created",
12
"_shards" : {
13
"total" : 2,
14
"successful" : 2,
15
"failed" : 0
16
},
17
"_seq_no" : 0,
18
"_primary_term" : 1,
19
"status" : 201
20
}
21
},
22
{
23
"index" : {
24
"_index" : "my_number",
25
"_type" : "_doc",
26
"_id" : "2",
27
"_version" : 1,
28
"result" : "created",
29
"_shards" : {
30
"total" : 2,
31
"successful" : 2,
32
"failed" : 0
33
},
34
"_seq_no" : 1,
35
"_primary_term" : 1,
36
"status" : 201
37
}
38
},
39
{
40
"index" : {
41
"_index" : "my_number",
42
"_type" : "_doc",
43
"_id" : "3",
44
"_version" : 1,
45
"result" : "created",
46
"_shards" : {
47
"total" : 2,
48
"successful" : 2,
49
"failed" : 0
50
},
51
"_seq_no" : 2,
52
"_primary_term" : 1,
53
"status" : 201
54
}
55
},
56
{
57
"index" : {
58
"_index" : "my_number",
59
"_type" : "_doc",
60
"_id" : "4",
61
"status" : 400,
62
"error" : {
63
"type" : "mapper_parsing_exception",
64
"reason" : "failed to parse field [number_val] of type [byte] in document with id '4'. Preview of field's value: '1024'",
65
"caused_by" : {
66
"type" : "illegal_argument_exception",
67
"reason" : "Value [1024] is out of range for a byte"
68
}
69
}
70
}
71
}
72
]
73
}
Copied!
먼저 number_val 은 byte 이기 때문에 "_id": "4" 도큐먼트인 1024 값은 색인이 되지 않고 오류가 발생합니다. 이제 range 쿼리를 이용해서 3 보다 크거나 같고 4.2 보다 작은 값을 검색 해 봅니다.
request
response
3 이상, 4.2 미만인 값 검색
1
GET my_number/_search
2
{
3
"query": {
4
"range": {
5
"number_val": {
6
"gte": 3,
7
"lt": 4.2
8
}
9
}
10
}
11
}
Copied!
3 이상, 4.2 미만인 값 검색 결과
1
{
2
"took" : 1,
3
"timed_out" : false,
4
"_shards" : {
5
"total" : 1,
6
"successful" : 1,
7
"skipped" : 0,
8
"failed" : 0
9
},
10
"hits" : {
11
"total" : {
12
"value" : 2,
13
"relation" : "eq"
14
},
15
"max_score" : 1.0,
16
"hits" : [
17
{
18
"_index" : "my_number",
19
"_type" : "_doc",
20
"_id" : "1",
21
"_score" : 1.0,
22
"_source" : {
23
"number_val" : 3
24
}
25
},
26
{
27
"_index" : "my_number",
28
"_type" : "_doc",
29
"_id" : "2",
30
"_score" : 1.0,
31
"_source" : {
32
"number_val" : 4.5
33
}
34
}
35
]
36
}
37
}
Copied!
분명 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 가 저장되기 때문에 나중에 검색이나 집계에 오류가 발생하게 됩니다.
Copy link