
엘라스틱서치의 인덱스는 아주 세부적인 부분까지 제어 가능하고, 설정에 따라 동작과 특성이 극단적으로 달라지므로 설계가 중요합니다.
이번 챕터에서는 설정 방법 및 매핑, 필드타입 등에 대해 다룹니다.
인덱스를 생성할 때에는 인덱스의 동작에 관한 설정을 지정할 수 있습니다.
인덱스 설정을 조회하려면 인덱스 이름 뒤에 /_settings를 넣어 GET 메서드로 호출합니다.
GET [인덱스 이름]/_settings
이전 챕터에서 만들었던 my_index를 재사용하겠습니다.
예시 요청
GET my_index/_settings예시 응답
{ "my_index": { "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "1", "provided_name": "my_index", "creation_date": "1760278432742", "number_of_replicas": "1", "uuid": "tT1hQxmERIOPyeaknWd1gg", "version": { "created": "9033000" } } } } }
number_of_shards, number_of_replicas라는 설정이 보입니다. 이에 관해서는 후술하겠습니다. refresh_interval이라는 중요한 설정이 있는데, 이 응답에는 포함되지 않았습니다.
이에 관해서도 다뤄보겠습니다.
number_of_shards는 인덱스를 구성하는 기본(primary) 샤드의 개수를 의미합니다. 엘라스틱서치는 데이터를 여러 샤드로 분할(sharding)하여 저장함으로써, 대용량 데이터의 병렬 처리와 확장성을 확보합니다. 기본값은 1이지만, 대규모 데이터를 저장하거나 색인 속도를 높이기 위해 더 많은 샤드로 나누어 구성할 수 있습니다. 다만 샤드 수가 많아질수록 오버헤드(메모리, 파일 핸들, 클러스터 관리 비용) 가 증가하기 때문에, 데이터 크기와 사용 패턴을 고려해 신중히 설정하는 것이 좋습니다. 일반적으로 하나의 샤드는 20~50GB 수준이 되도록 조정하는 것이 권장됩니다.
주의할 점은, 이 설정은 인덱스 생성 이후에는 변경할 수 없습니다. 즉, number_of_shards는 비가역적(immutable) 설정이며, 인덱스를 새로 생성하지 않는 이상 수정이 불가능합니다. 만약 기존 인덱스의 샤드 구성을 변경해야 한다면 _reindex API를 사용해 새 인덱스를 생성한 뒤 데이터를 옮겨야 합니다.
일반적으로 하나의 샤드는 20~50GB 수준이 되도록 조정하는 것이 권장되며, 불필요하게 많은 샤드를 두면 **오버헤드(메모리, 파일 핸들, 클러스터 관리 비용)**가 증가합니다. 따라서 데이터 크기와 질의 부하를 고려해 신중히 결정하는 것이 좋습니다.
number_of_replicas는 각 기본 샤드에 대해 몇 개의 복제(replica) 샤드를 유지할지를 정의하는 설정입니다. 복제본은 장애가 발생했을 때 데이터 손실을 방지하고, 검색 요청을 여러 노드에 분산시켜 조회 성능을 향상시키는 역할을 합니다. 기본값은 1이며, 이는 각 기본 샤드마다 하나의 복제본이 존재한다는 뜻입니다. 복제본은 기본 샤드와 같은 노드에는 배치되지 않으며, 다른 노드로 자동 분산되어 고가용성을 제공합니다. 만약 클러스터에 노드가 하나뿐이라면 복제본은 할당되지 않고, “UNASSIGNED” 상태로 남게 됩니다.
이 설정은 인덱스 생성 후에도 동적으로 변경 가능합니다. 따라서 트래픽이 적은 개발 환경에서는 number_of_replicas: 0으로 두었다가, 운영 환경에서 노드를 확장한 후 1 이상으로 변경하여 복제본을 추가하는 식의 조정이 가능합니다.
refresh_interval은 새로 색인된 문서가 검색 가능해지기까지의 주기를 의미합니다. 엘라스틱서치는 내부적으로 세그먼트(segment) 를 메모리에 유지하다가, 일정 주기마다 이를 루씬(Lucene) commit과 함께 새로고침(refresh) 하여 검색 인덱스에 반영합니다. 기본값은 1초이며, 즉 새로 추가된 문서는 최대 1초 이내에 검색 결과에 나타나게 됩니다. 만약 색인 작업이 대량으로 이루어지는 배치 환경이라면, refresh_interval 값을 일시적으로 늘려서 색인 성능을 높이고 디스크 I/O를 줄일 수 있습니다. 예를 들어 대규모 데이터 로딩 중에는 refresh_interval을 -1로 설정하여 자동 새로고침을 비활성화하고, 모든 색인이 완료된 후 수동으로 refresh를 수행하는 방식이 자주 사용됩니다.
앞서 사용한 my_index는 인덱스가 없는 상태에서 문서 색인을 요청하여 자동으로 생성된 인덱스였습니다. 이런 방법으로 자동 생성된 인덱스는 모두 기본 설정값이 지정되는데요, 실제 운영환경에서 이렇게 기본 설정값을 사용하는 것은 적절하지 않습니다.
이번 파트에서는 인덱스를 수동으로 생성하고 삭제하는 방법을 알아보겠습니다.
다음과 같이 요청하면 수동으로 인덱스를 생성할 수 있지만 기본 설정값으로 인덱스가 생성됩니다.
PUT [인덱스 이름]
예시 요청
PUT my_index2예시 응답
{ "acknowledged": true, "shards_acknowledged": true, "index": "my_index2" }응답 필드 설명
- acknowledged: 클러스터가 인덱스 생성 요청을 정상적으로 수락했는지를 나타냅니다.
true이면 인덱스 생성이 성공적으로 승인되었음을 의미합니다.- shards_acknowledged: 인덱스를 구성하는 모든 샤드가 정상적으로 초기화되었는지를 의미합니다.
true이면 모든 기본(primary) 샤드가 클러스터 내에서 성공적으로 할당된 상태입니다.- index: 생성된 인덱스의 이름을 나타냅니다. 이 경우
"my_index2"인덱스가 생성되었습니다.
기본 인덱스를 원하는 것이 아니기 때문에 삭제하고 다시 만들겠습니다.
예시 요청
DELETE my_index2 PUT my_index2 { "settings": { "number_of_replicas": 1, "number_of_shards": 2 } } GET my_index2예시 응답
{ "my_index2": { "aliases": {}, "mappings": {}, "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "2", "provided_name": "my_index2", "creation_date": "1760166113743", "number_of_replicas": "1", "uuid": "rAstZgxsRXm9AoiaMLBxsg", "version": { "created": "9033000" } } } } }
응답에서 mapping타입을 추가로 확인할 수 있다. 지금은 비어있다. 이에 관해서 알아봅시다.
매핑은 문서가 인덱스에 어떻게 색인되고 저장되는지 정의하는 부분이다. Json 문서의 각 필드를 어떤 방식으로 분석하고 색인할지, 어떤 타입으로 저장할지 등을 세부적으로 지정할 수 있습니다.
방금 만들었던 my_index2 인덱스에 다음과 같이 문서를 하나 색인하고 인덱스 정보를 확인해봅시다.
먼저 문서를 색인합니다.
예시 요청
PUT my_index2/_doc/1 { "title": "hello world", "views": 1234, "public": true, "point": 4.5, "created": "2025-10-12T14:05:01.234Z" }예시 응답
{ "_index": "my_index2", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 2, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 }
내용을 확인합니다.
예시 요청
GET my_index2예시 응답
{ "my_index2": { "aliases": {}, "mappings": { "properties": { "created": { "type": "date" }, "point": { "type": "float" }, "public": { "type": "boolean" }, "title": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } }, "views": { "type": "long" } } }, "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "2", "provided_name": "my_index2", "creation_date": "1760166113743", "number_of_replicas": "1", "uuid": "rAstZgxsRXm9AoiaMLBxsg", "version": { "created": "9033000" } } } } }
이전에 인덱스 정보 요청시 비어있던 mappings 항목 밑에 각 필드 타입과 관련된 정보가 새로 생겼습니다. 이렇게 인덱스에 문서가 색인될 때 기존에 매핑 정보를 가지고 있지 않던 새로운 필드가 들어오면 ES는 자동으로 문서의 내용을 보고 필드 타입을 유추하여 매핑 정보를 생성합니다.
이전에 엘라스틱 서치가 자동으로 생성한 매핑을 동적 매핑(Dynamic mapping)이라고 부르고, 반대로 사용자가 직접 매핑을 지정해 주는 방법을 명시적 매핑(Explicit mapping)이라고 부릅니다.
다음과 같이 매핑 정보를 명시적으로 지정해서 인덱스를 생성해봅시다.
예시 요청
PUT mapping_test { "mappings": { "properties": { "createdDate": { "type": "date", "format": "strict_date_time || epoch_millis" }, "keywordString": { "type": "keyword" }, "textString": { "type": "text" } } }, "settings": { "number_of_replicas": 1, "number_of_shards": 1 } } GET mapping_test예시 응답
{ "mapping_test": { "aliases": {}, "mappings": { "properties": { "createdDate": { "type": "date", "format": "strict_date_time || epoch_millis" }, "keywordString": { "type": "keyword" }, "textString": { "type": "text" } } }, "settings": { "index": { "routing": { "allocation": { "include": { "_tier_preference": "data_content" } } }, "number_of_shards": "1", "provided_name": "mapping_test", "creation_date": "1760285310361", "number_of_replicas": "1", "uuid": "YwI1-lT7Tr6v66LfcgBR5g", "version": { "created": "9033000" } } } } }
이미 인덱스가 생성된 경우에도 신규 필드를 추가할 경우에는 매핑 정보를 추가할 수 있습니다.
PUT mapping_test/_mapping
{
"properties": {
"longValue": {
"type": "long"
}
}
}
매핑의 기본은 필드 타입입니다. 필드 타입은 필드의 값이 어떤 형태로 저장될지를 지정합니다. 필드 타입은 한 번 지정되면 변경이 불가능하므로 매우 신중하게 지정해야합니다.
| 분류 | 대표 타입 | 저장/색인 특성 | 주요 사용처 | 주의사항/제한 |
|---|---|---|---|---|
| 심플 타입 | keyword |
분석 없이 원문 그대로 색인, 정렬·집계에 유리 | 식별자, 카테고리, 상태값 | ignore_above 길이 제한, 대소문자/공백 정규화는 normalizer 고려 |
text |
애널라이저로 토큰화, 풀텍스트 검색 최적화 | 본문, 제목 | 집계/정렬 비효율 → keyword 서브필드 병행 설계 권장 |
|
long / integer / double / scaled_float |
수치형 집계·범위 질의에 빠름 | 점수, 수량, 가격 | scaled_float 스케일 고정 필요, 부동소수 정밀도 주의 |
|
boolean |
true/false 저장 |
플래그 | 문자열 "true"/"false" 유입 주의 |
|
date |
문자열/epoch를 파싱해 저장 | 생성일, 갱신일 | 포맷 자동추론보다 일관 포맷 고정 권장 | |
ip |
IPv4/IPv6 저장 | IP 로그 | CIDR 범위 질의 지원 | |
| 계층 타입 | object |
평탄화되어 저장(중첩 문서 아님) | 단순 하위 필드 묶음 | 다값일 때 교차 매칭 문제 발생 가능 |
nested |
배열 각 요소를 독립 문서처럼 색인 | 배열 내 객체의 정확 매칭 | nested 쿼리 필요, 조인 비용 증가 → 쿼리 패턴 선설계 |
|
| 특수 타입 | geo_point |
위도/경도 점 저장 | 반경/박스 내 위치 검색 | 좌표(lat, lon) 순서 주의 |
geo_shape |
선/다각형/멀티폴리곤 등 도형 | 영역 포함·교차 질의 | 인덱싱/질의 비용 큼, 좌표계·정밀도 고려 | |
completion |
자동완성 서제스트 전용 구조 | 검색어 추천 | 전용 suggest 쿼리, 메모리 사용량 주의 | |
join |
단일 인덱스 내 부모-자식 관계 | 희소 관계 모델링 | 쿼리 복잡·비용 증가 → 가능하면 denormalize 우선 | |
rank_feature / rank_features |
랭킹용 스칼라/벡터 특성 | 학습랭킹(LETOR) | 전용 쿼리로만 활용 가능 | |
dense_vector |
고정 길이 벡터 | 벡터 유사도 검색 | kNN/ANN 사용은 버전·라이선스 제약 가능 | |
histogram |
히스토그램 bin/카운트 | 시계열 집계 최적화 | 입력 형식 엄격, 전처리 필요 |
💡계층 구조를 지원하는 타입:
objectvsnested
object와nested타입은 모두 JSON 객체를 저장하지만, 배열 내부에 객체가 포함될 때 색인 방식과 검색 동작에서 결정적인 차이를 보입니다. 핵심은 배열 내 객체 요소들의 연관성을 유지하는지 여부입니다.예시 데이터
예를 들어, 사용자별 권한을 나타내는 다음과 같은 문서가 있다고 가정해 봅시다.
{ "permissions": [ { "service": "board", "level": "read" }, { "service": "account", "level": "write" } ] }우리는 "account" 서비스에 "read" 권한을 가진 사용자가 아닌, "account" 서비스에 "write" 권한을 가진 사용자를 찾고 싶습니다.
1.
object타입의 동작 (기본값)
permissions필드를object타입 (기본값)으로 매핑하면, 엘라스틱서치는 내부적으로 데이터를 다음과 같이 평탄화(flatten)하여 색인합니다.{ "permissions.service": [ "board", "account" ], "permissions.level": [ "read", "write" ] }이 구조에서는
board와read가,account와write가 원래 같은 객체였다는 연관성이 사라집니다.이 상태에서 "service가 account이고 level이 read인" 문서를 찾으려고 다음 쿼리를 실행하면 어떻게 될까요?
GET /_search { "query": { "bool": { "must": [ { "match": { "permissions.service": "account" } }, { "match": { "permissions.level": "read" } } ] } } }위 쿼리는 의도치 않게 예시 문서를 결과로 반환합니다. 왜냐하면
permissions.service필드에account가 존재하고,permissions.level필드에read가 존재하기 때문입니다. 각 필드가 독립적으로 조건을 만족시키므로 AND 조건이 참이 됩니다. 이를 교차 매칭(cross-match) 문제라고 합니다.2.
nested타입의 동작이 문제를 해결하기 위해
nested타입을 사용합니다.permissions필드를nested로 명시적으로 매핑하면, 엘라스틱서치는 배열의 각 객체를 **독립된 숨은 문서(hidden document)**로 취급하여 색인합니다.
{ "service": "board", "level": "read" }(하나의 독립 문서로 색인){ "service": "account", "level": "write" }(또 다른 독립 문서로 색인)이렇게 하면 각 객체 내의 필드 연관성이 그대로 유지됩니다.
하지만
nested필드를 검색할 때는 일반적인 쿼리로는 부족합니다.nested데이터 구조는 특별하게 취급되기 때문에, 전용nested쿼리를 사용해야만 합니다. 만약 위에서 사용했던bool쿼리를 그대로nested필드에 사용하면,object타입과 마찬가지로 원하는 결과를 얻을 수 없거나 아무 결과도 반환하지 못할 수 있습니다.올바른
nested쿼리는 다음과 같습니다.GET /_search { "query": { "nested": { "path": "permissions", "query": { "bool": { "must": [ { "match": { "permissions.service": "account" } }, { "match": { "permissions.level": "write" } } ] } } } } }이 쿼리는
permissions경로 내의 숨은 문서들 각각에 대해bool쿼리를 실행하므로,service가account이면서 동시에level이write인 객체가 존재하는 문서만을 정확하게 찾아낼 수 있습니다.참고:
nested_fields.limitnested필드 타입은 내부적으로 숨은 문서를 생성하므로, 하나의 문서에 포함될 수 있는nested객체의 수에는 제한이 있습니다. 이 제한은index.mapping.nested_fields.limit설정으로 제어되며, 기본값은50입니다. 만약 이보다 많은nested객체를 색인해야 한다면, 인덱스 설정에서 이 값을 늘려주어야 합니다.
문자열 데이터는 사용 목적에 따라 전문 검색(Full-text Search) 을 위한 text 타입과 정확한 값(Exact-value) 필터링, 정렬, 집계를 위한 keyword 타입으로 나뉩니다. 두 타입은 데이터를 색인하고 검색하는 방식이 근본적으로 다르며, 이는 doc_values와 fielddata라는 내부 데이터 구조와 깊은 관련이 있습니다.
text 타입: 분석을 통한 전문 검색
text 타입은 분석(Analysis) 과정을 거쳐 저장됩니다. 분석은 애널라이저(Analyzer)에 의해 수행되며, 보통 다음과 같은 3단계로 이루어집니다.
색인 예시
원본 문자열:
"Quick Brown Fox"
standard애널라이저 적용 후 색인된 텀들:["quick", "brown", "fox"]
이렇게 분리된 텀들이 역 인덱스(Inverted Index)에 저장되어, 검색 시 어떤 단어가 어떤 문서에 포함되어 있는지 빠르게 찾을 수 있습니다. 따라서 "Fox"나 "Quick" 같은 단어로 검색하면 위 문서가 결과로 반환됩니다. 즉, text 필드는 내용 기반의 부분 일치 검색에 최적화되어 있습니다.
text와 fielddata
text 필드는 기본적으로 정렬이나 집계에 사용될 수 없습니다. 이를 가능하게 하려면 fielddata=true 옵션을 주어야 하는데, 이 경우 JVM 힙 메모리에 모든 텀을 로드하는 fielddata라는 구조를 사용합니다. fielddata는 매우 큰 메모리를 소비하므로, 운영 환경에서는 메모리 부족(Out of Memory)을 유발할 수 있어 사용을 극도로 주의해야 합니다.
keyword 타입: 분석 없는 정확한 값
keyword 타입은 분석 과정을 거치지 않고, 입력된 문자열 전체를 하나의 텀으로 색인합니다.
색인 예시
원본 문자열:
"Quick Brown Fox"
keyword타입으로 색인된 텀:["Quick Brown Fox"]
따라서 keyword 필드를 검색할 때는 "Quick Brown Fox"라는 전체 문자열과 정확히 일치해야만 결과로 반환됩니다. "Fox"나 "quick brown fox"(대소문자 다름)로 검색하면 문서를 찾을 수 없습니다.
이러한 특성 때문에 keyword 타입은 카테고리, 태그, 상태 코드, 식별자 등 **필터링, 정렬, 집계(Aggregation)**에 사용하기에 이상적입니다.
keyword와 doc_values
keyword 타입은 기본적으로 doc_values를 활성화하여 사용합니다. doc_values는 fielddata와 달리 JVM 힙이 아닌 디스크 기반의 컬럼형 데이터 구조입니다. 문서를 행(row)으로, 필드를 열(column)으로 생각했을 때, 특정 필드의 값들만 수직으로 모아 저장하는 방식입니다.
이 구조는 정렬이나 집계 시 필요한 데이터만 효율적으로 디스크에서 읽어올 수 있게 해주므로, 힙 메모리 사용 없이도 매우 빠르고 효율적인 성능을 보장합니다. 이것이 keyword 필드가 집계 및 정렬에 사용되는 이유입니다.
text vs keyword 요약
| 구분 | text |
keyword |
|---|---|---|
| 분석(Analysis) | O (애널라이저 적용) | X (원본 그대로 저장) |
| 주요 용도 | 전문 검색 (Full-text Search) | 필터링, 정렬, 집계 |
| 검색 방식 | 부분/단어 일치 | 완전 일치 |
| 정렬/집계 데이터 구조 | fielddata (힙 메모리, 기본 비활성) |
doc_values (디스크, 기본 활성) |
💡 다중 필드(Multi-fields) 활용
실제로는 하나의 필드를 전문 검색과 정렬/집계 양쪽으로 모두 사용하고 싶을 때가 많습니다. 이 경우, 엘라스틱서치의 다중 필드(Multi-fields) 기능을 사용하면 됩니다. 동적 매핑 시
title필드가title.keyword라는 서브 필드를 가지는 것이 바로 이 기능 때문입니다.
title필드 (text타입): 전문 검색용title.keyword필드 (keyword타입): 정렬 및 집계용이렇게 설정하면 하나의 원본 데이터로 두 가지 목적을 모두 효율적으로 달성할 수 있습니다.
doc_values는 정렬, 집계, 스크립팅을 위해 사용되는 디스크 기반의 컬럼형 데이터 구조입니다.
text 타입을 제외한 모든 필드 타입(keyword, numeric, date, boolean 등)에 기본적으로 활성화됩니다.
doc_values비활성화 예시정렬이나 집계에 절대 사용되지 않을 필드라면
doc_values를 비활성화하여 디스크 공간을 약간 절약할 수 있습니다.PUT my-index { "mappings": { "properties": { "session_id": { "type": "keyword", "doc_values": false } } } }주의: 한 번 비활성화하면 해당 필드는 더 이상 정렬, 집계, 스크립트에서 접근할 수 없습니다.
fielddata는 text 필드에 대한 정렬 및 집계를 가능하게 하는 JVM 힙 메모리 기반의 데이터 구조입니다.
text 필드는 doc_values를 사용할 수 없기 때문에 fielddata를 사용합니다.
text 필드는 분석 과정을 거쳐 여러 텀으로 나뉩니다. fielddata는 이 모든 텀들을 메모리(JVM 힙)에 로드하여 정렬이나 집계가 가능하도록 만듭니다.text 필드에 대해 기본적으로 비활성화되어 있습니다.
fielddata활성화 예시
text필드에 대해 집계가 꼭 필요한 경우에만 제한적으로 사용해야 합니다.PUT my-index { "mappings": { "properties": { "description": { "type": "text", "fielddata": true } } } }경고:
fielddata활성화는 매우 신중해야 합니다. 대부분의 경우,text필드에.keyword와 같은 다중 필드를 추가하여doc_values기반으로 집계하는 것이 훨씬 안전하고 효율적입니다.
이에 관한 문제는 토스의 SLASH 23 - 대규모 로그 처리도 OK! Elasticsearch 클러스터 개선기에서도 확인할 수 있습니다.
_source 필드는 색인 시 전송한 원본 JSON 문서를 그대로 저장하는 특수한 메타 필드입니다.
hits._source 부분에 원본 문서를 표시합니다._source에서 문서를 가져와 변경한 뒤 전체를 다시 색인합니다._source를 원본 데이터로 사용합니다._source 자체는 검색되지 않으며(not indexed), 단순히 저장만 됩니다.
_source비활성화 예시
_source를 비활성화하면 상당한 디스크 공간을 절약할 수 있지만, 원본 문서를 볼 수 없게 되는 등 여러 기능에 제약이 생깁니다.PUT my-index { "mappings": { "_source": { "enabled": false } } }주의:
_source를 비활성화하면 검색 결과에서 원본 문서를 확인할 수 없으며, update, reindex 등의 API 사용이 불가능해집니다. 디스크 공간 절약이 매우 중요한 특수한 경우가 아니라면 활성화 상태로 두는 것이 좋습니다.
💡
_source저장 공간 최적화
_source를 완전히 비활성화하는 대신, 저장 공간을 절약할 수 있는 다른 방법도 있습니다.
- 인덱스 코덱 변경: 인덱스 설정에서
index.codec을best_compression으로 지정하면, CPU를 조금 더 사용하는 대신 디스크 저장 공간을 우선적으로 절약하도록 압축률을 높일 수 있습니다.- Synthetic Source:
_source를 비활성화하는 대신synthetic source를 사용할 수 있습니다. 이는doc_values와stored_fields를 조합하여_source를 동적으로 재구성하는 기능으로, 원본_source를 저장하지 않으면서도 일부 기능을 유지할 수 있게 해줍니다.
index 파라미터는 필드의 검색 가능 여부를 제어합니다.
index가 true(기본값)이면 필드의 내용은 분석되어 역 인덱스에 추가됩니다. false로 설정하면 필드의 값은 _source에는 저장되지만, 역 인덱스에는 추가되지 않아 검색할 수 없게 됩니다.index: false로 설정된 필드는 쿼리 대상이 될 수 없습니다. 색인 속도를 약간 향상시키고, 아주 약간의 디스크 공간을 절약하는 효과가 있습니다.
index: false설정 예시
image_url필드는 검색에 사용하지 않고, 결과로 받아 화면에 이미지를 표시하는 용도로만 사용한다고 가정합니다.PUT my-index { "mappings": { "properties": { "product_name": { "type": "text" }, "image_url": { "type": "keyword", "index": false } } } }
enabled 파라미터는 JSON 객체 필드 전체의 분석 여부를 제어합니다. index 파라미터가 개별 필드에 적용되는 반면, enabled는 객체 타입 필드나 최상위 매핑에 적용됩니다.
enabled가 true(기본값)이면 엘라스틱서치는 객체 내부의 모든 필드를 파싱하고 매핑합니다. false로 설정하면 해당 JSON 객체의 내용은 전혀 파싱되지 않고, _source에 원본 그대로 저장되기만 합니다.enabled: false로 설정된 객체는 그 내부의 어떤 필드로도 접근하거나 검색할 수 없습니다. 객체 전체가 단일 값처럼 취급됩니다. 색인 성능을 크게 향상시킬 수 있습니다.
enabled: false설정 예시
raw_log필드에 외부 시스템으로부터 받은 복잡한 JSON 로그를 저장하지만, 그 내용을 검색할 필요는 없는 경우입니다.PUT my-index { "mappings": { "properties": { "log_id": { "type": "keyword" }, "raw_log": { "type": "object", "enabled": false } } } }
다음 챕터에서는 애널라이저, 템플릿, 라우팅에 대해 알아보겠습니다.