데이터 타입 변환에 대해 알아보기 전에 먼저 이 거 한번 봐주세요.
다음 중 정수 5는?
1. "5"
2. 오
3. 5.0
4. 5
정답은 4입니다. 그럼 오답풀이를 해볼까요?
1번은 문자 5
2번도 그냥 문자 5
3번은 부동소수점 5.0
5.000001이나 5.0이나 5나 사실 그냥 5는 5인데... 자료형이 앞에 붙으면 int 5 랑 float 5.0은 느낌이 너무 다르네요.
엘라스틱서치는 데이터 타입을 정해진 규칙에 따라서 변환을 해줘요. 예를 들면, 정수형 데이터만 받기로 한 number_one이라는 필드에 문자열 값 "5"가 들어오면 이 건 사실 에러가 나야 하는 건데 엘라스틱서치에서는 coercion이라는 기능을 통해서 문자열 "5"를 정수로 바꿀 수 있는지 확인하고 바꿀 수 있다면 정수로 바꿔서 넣어줘요. 부동 소수 5.0도 마찬가지로 정수형으로 변환이 가능하면 정수형으로 변환해서 넣어줘요. 그런데 보기 2번과 같이 리터럴 하게 '오', "오", "five", 'FIVE' 이런 건 못 바꿔줘요. 아니 안 바꿔줘요. 이 거 바꿔주면 아마 더 머리에서 쥐가 날 꺼 같아요. '사만 참천이 십육'. 이런 거. 바꿔준다고 하면 큰일 날 거 같아요. 문제가 생기면 찾기 너무 힘들 거 같아서요.
인덱스의 매핑을 확인해서 어떤 필드에 어떤 데이터 타입을 넣을지 볼 수 있는 건 이미 알아요. 그럼 간단하게 인덱스에 몇몇 타입의 데이터를 넣어보고 어떻게 동작하는지, 이 coercion 기능을 끄는 건 어떻게 끄는지, 끄면 어떻게 동작하는지 알아보아요.
...
"number_one": {
"type": "integer"
},
"number_two": {
"type": "integer",
"coerce": false
}
...
먼저 매핑을 만들어주는 요청에서 볼 거는 coerce라는 매핑 파라미터를 명시적으로 false라고 알려주지 않으면 기본적으로는 true인가 보다.라는 걸 알 수 있어요. 다음.
POST /data_coercion/_doc/1
{
"number_one": "10"
}
큰따옴표로 묶은 문자열 데이터 타입이라도 coerce 옵션이 (default로) true이기 때문에 정수로 변환되어서 저장되었을 것 같아요. 왜냐하면 에러가 안 났으니까요. 그럼 확인을 해볼게요.
"_source" : {
"number_one" : "10"
}
음? number_one에 문자열로 들어가 있네?
10초만 생각해보세요.
_source에는 인덱싱 할 당시의 모습 그대로 들어가고 엘라스틱서치 내부에서는 변환해서 저장된다고 했어요.
그럼 어떻게 확인해볼 수 있을까요? 만약 문자열이라면 집계나 정렬에 사용할 수 없을 거예요.
POST /data_coercion/_search
{
"query": {
"range": {
"number_one": {
"gte": 9
}}}}
number_one에서 9보다 크거나 같은 값을 찾아주세요.
했더니 _doc/1이 나왔어요. 10보다 크거나 같은 걸 찾아주세요 해도 나왔어요. 11보다 크거나 같은 걸 찾아달라 하니 없대요.
확실히 정수형으로 저장되었나 봐요. 정렬도 되는 거 보면. 그럼 이제 coerce를 false로 설정해 놓은 number_two에 한 번 값을 넣어볼게요.
POST /data_coercion/_doc/2
{
"number_two": "10"
}
POST /data_coercion/_doc/2
{
"number_two": 10
}
첫 번째 요청은 에러가 날 거고, 두 번째 요청은 정상적으로 값이 들어갈 거예요.
이렇게 해서 엘라스틱서치에서 강제적으로 형 변환이 어떻게 이루어지는지 확인해봤어요.
데이터 타입을 정수형으로 정의하고 문자열 안에 들어간 정수가 형 변환이 되는지 봤어요.
그럼 10.1은 어떻게 들어갈까요? 9.9는?
float으로 정의해 놓은 필드에 정수를 넣으면 어떻게 들어갈까요?
매핑을 수정해서 float형 필드를 하나 더 넣어볼게요.
PUT /data_coercion/_mapping
{
"properties": {
"num_float": {
"type": "float"
}
}
}
여기에 정수도 넣어보고 문자열로도 넣어보면 되겠네요.
그런데 이렇게 알아서 바꿔줘서 들어가는 것도 때로는 편하고 좋을 때도 있지만 때로는 불편할 때도 있어요. 그럴 때는 "coerce": false를 사용하면 좋을 거 같아요.
https://www.elastic.co/guide/en/elasticsearch/reference/7.14/coerce.html
coerce | Elasticsearch Guide [7.14] | Elastic
Data is not always clean. Depending on how it is produced a number might be rendered in the JSON body as a true JSON number, e.g. 5, but it might also be rendered as a string, e.g. "5". Alternatively, a number that should be an integer might instead be ren
www.elastic.co