티스토리 뷰
안녕하세요. 개발개입니다.
위키북스에서 나온 <엘라스틱서치 실무 가이드>를 공부하면서
정리한 부분을 다음과 같은 목차에 따라 공유합니다.
(설치와 관련된 포스트는 많기 때문에 따로 작성하지 않았습니다.)
이번 글에서는 데이터 모델링과 관련하여 다음에 내용에 대해 다룹니다.
목차
- 매핑 파라미터
- 메타 필드
- 데이터 타입
오타, 오류 혹은 기타 의견은 언제든지 환영합니다.
1. 매핑 파라미터
- anlayzer
-
해당 필드의 데이터를 형태소 분석의 대상으로 함
-
색인 및 검색 시 지정한 분석기로 형태소 분석을 수행 (디폴트 standard analyzer)
- normalizer
-
term query에 분석기를 사용하기 위함
-
asciifolding 필터를 사용하면 cafe, Cafe, Café를 같은 데이터로 인식
- boost
-
필드에 가중치 부여 → 유사도(_score) 산출이 달라짐 → 검색 결과 노출 순서에 영향
-
색인 시점에서 사용하면 가중치를 변경할 수 없으므로 검색 시점에서 사용하는 것을 권장
(루씬7.0부터 색인 시 BOOST 설정 기능이 제거되어 최신 엘라스틱 서치도 불가능해짐)
- coerce
-
색인 시 자동 변환을 허용할지 여부
- copy_to
-
해당 필드의 값을 지정한 필드로 복사
(keyword to text인 경우, 형태소 분석도 가능)
- fielddata
-
엘라스틱서치가 힙 공간에 생성하는 메모리 캐시
-
형태소 분석을 하는 text 타입의 경우 집계/정렬을 수행하기 위해 사용
-
메모리 부족 현상 등으로 최소한 사용 권장
-
디폴트는 false, 활성화 코드는 아래 참고
PUT [인덱스명]/_mapping/_doc
{
"properties" : {
"[컬럼명]" : {
"type" : "text",
"fielddata" : true
}
}
}
- doc_values
-
엘라스틱서치 기본 캐시 (루씬 기반)
-
text 타입을 제외한 모든 타입에서 기본적으로 사용
-
한 번 비활성화된 필드는 재색인해야 변경 가능
- dynamic
-
매핑에 필드를 추가할 때 동적으로 할지 말지 여부
-
true
-
false(무시되므로 검색불가, _source엔 있음)
-
strict (새로운 필드 감지 시 예외 발생)
-
- enabled
-
검색 결과(_source)에는 포함하지만 색인은 하고 싶지 않은 경우 (e.g. 메타 데이터)
- format
-
날짜/시간을 문자열로 변경 시 포매팅
포맷 | 날짜 형식 | 비고 |
basic_date | yyyyMMdd | 년도/월/일 |
basic_date_time | yyyyMMdd'T'HHmmss.SSSZ | 년도/월/일/T/시/분/초/밀리초/Z |
basic_time | HHmmss.SSS | 시/분/초/밀리초/Z |
date/strict_date | yyyy-MM-dd | 년도/시/분 |
date_hour_minute_second/ strict_date_hore_minute_second |
yyyy-MM-dd'T'HH:mm:ss. | 년도/시/분/T/시/분/초 |
date_hour_misnute_second_millis/ strict_date_hour_minute_second_millis |
yyyy-MM-dd'T'HH:mm:ss.SSS | 년도/시/분/T/시/분/초/밀리초 |
date_time/strict_date_time | yyyy-MM-dd'T'HH:mm:ss.SSSZZ | 년도/시/분/T/시/분/초/밀리초/ZZ |
- ignore_above
- 지정한 크기를 넘어선 필드 문자열을 빈 값으로 색인
- ignore_malformed
- 예외가 발생하는 필드를 무시하고 문서를 색인
- index
-
필드값을 색인할지 여부 (디폴트는 true)
- fields
-
멀티 필드를 설정할 수 있는 옵션
- norms
-
_score 값 계산에 필요한 정규화 인수를 사용할 지 여부 (디폴트는 true)
-
_score 값 계산이 불필요하고 단순 필터링 용도의 필드는 비활성화 함으로써 디스크 공간 절약
- null_value
- 필드 값이 null이더라도 필드를 생성
(기본적으로는 색인 시 문서에 필드가 없거나 값이 null이면 필드를 생성하지 않음)
PUT [인덱스명]/_mapping/_doc
{
"properties" : {
"[컬럼명]" : {
"type" : "integer",
"null_value" : "0"
}
}
}
- position_increment_gap
-
필드 데이터 중 단어와 단어 사이의 간격(slop)을 허용할지 여부
-
배열 형태의 베이터를 색인할 때 검색의 정확도를 높임
(e.g. 데이터가 ["apple mango", "juice mixer"]일 때, "mango juice"로도 검색이 가능)
- properties
-
Object 타입이나 Nested(중첩) 타입의 스키마를 정의할 때 사용
- search_analyzer
-
색인과 검색에 다른 분석기를 사용하고 싶은 경우, 검색 시 사용할 분석기 별도 설정
- similarity
-
유사도 측정 알고리즘 지정 (기본 알고리즘은 BM25)
- store
-
필드의 값을 저장해 검색 결과에 값을 포함하기 위한 매핑 파라미터
-
_source를 로드해서 해당 필드를 찾는 것보다 사용할 각 필드만 로드하는 것이 효율적이지만 디스크를 많이 사용함
- term_vector
-
루씬에서 분석된 용어 정보를 포함할지 여부
-
no / yes / with_positions / sith_offsets / with_positions_offsets
2. 메타 필드
_index
-
해당 문서가 속한 인덱스의 이름
-
해당 인덱스에 몇 개의 문서가 있는지 확인
POST [인덱스명]/_search
{
"size" : 0,
"aggs" : {
"indices" : {
"terms" : {
"field" : "_index",
"size" : 10
}
}
}
}
-
결과
{
"took" : 10,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 10,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"indices" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "[인덱스명]",
"doc_count" : 10
}
]
}
}
}
_type
-
해당 문서가 속한 매핑의 타입 정보
-
해당 인덱스 내에서 타입별로 몇 개의 문서가 있는지 확인
POST [인덱스명]/_search
{
"size" : 0,
"aggs" : {
"indices" : {
"terms" : {
"field" : "_type",
"size" : 10
}
}
}
}
-
결과
{
"took" : 2,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 10,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"indices" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "_doc",
"doc_count" : 10
}
]
}
}
}
_id
-
문서를 식별하는 유일한 키 값
-
해당 인덱스 내에서 키 값 별 문서 수 확인
POST [인덱스명]/_search
{
"size" : 0,
"aggs" : {
"indices" : {
"terms" : {
"field" : "_id",
"size" : 10
}
}
}
}
-
결과
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 10,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"indices" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "a4Y60nABDzsvV4duypRx",
"doc_count" : 1
},
{
"key" : "aoY10nABDzsvV4duY5T8",
"doc_count" : 1
},
{
"key" : "b4ZT0nABDzsvV4dusJRr",
"doc_count" : 1
},
{
"key" : "bIY70nABDzsvV4du45SB",
"doc_count" : 1
},
{
"key" : "bYY90nABDzsvV4duIZQs",
"doc_count" : 1
},
{
"key" : "c4ZX0nABDzsvV4dunJRx",
"doc_count" : 1
},
{
"key" : "cIZU0nABDzsvV4duX5SD",
"doc_count" : 1
},
{
"key" : "cYZV0nABDzsvV4duFZSl",
"doc_count" : 1
},
{
"key" : "dIZY0nABDzsvV4duaZSP",
"doc_count" : 1
},
{
"key" : "dYZa0nABDzsvV4duGpTT",
"doc_count" : 1
}
]
}
}
}
_uid
-
[_type]#[_id] 형태의 식별키 (내부적으로만 사용되므로 검색 시 조회되진 않음)
-
해당 인덱스 내에서 uid값 별 문서수 확인
POST [인덱스명]/_search
{
"size" : 0,
"aggs" : {
"indices" : {
"terms" : {
"field" : "_id",
"size" : 10
}
}
}
}
결과
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 10,
"max_score" : 0.0,
"hits" : [ ]
},
"aggregations" : {
"indices" : {
"doc_count_error_upper_bound" : 0,
"sum_other_doc_count" : 0,
"buckets" : [
{
"key" : "_doc#a4Y60nABDzsvV4duypRx",
"doc_count" : 1
},
{
"key" : "_doc#aoY10nABDzsvV4duY5T8",
"doc_count" : 1
},
{
"key" : "_doc#b4ZT0nABDzsvV4dusJRr",
"doc_count" : 1
},
{
"key" : "_doc#bIY70nABDzsvV4du45SB",
"doc_count" : 1
},
{
"key" : "_doc#bYY90nABDzsvV4duIZQs",
"doc_count" : 1
},
{
"key" : "_doc#c4ZX0nABDzsvV4dunJRx",
"doc_count" : 1
},
{
"key" : "_doc#cIZU0nABDzsvV4duX5SD",
"doc_count" : 1
},
{
"key" : "_doc#cYZV0nABDzsvV4duFZSl",
"doc_count" : 1
},
{
"key" : "_doc#dIZY0nABDzsvV4duaZSP",
"doc_count" : 1
},
{
"key" : "_doc#dYZa0nABDzsvV4duGpTT",
"doc_count" : 1
}
]
}
}
}
_source
-
문서의 원본 데이터 제공
-
원본 JSON 문서를 검색 결과로 표시할 때 사용
_all
-
색인에 사용된 모든 필드의 데이터를 하나의 텍스트로 합쳐서 제공
(e.g. [field1] || [field2 || … ) - 데이터 크기가 너무 커서 엘라스틱서치 6.0부터 없어졌고, copy_to를 이용해 동일하게 구현할 수 있음
_routing
-
특정 문서를 특정 샤드에 저장하기 위해 사용자가 지정하는 메타 필드
-
별도 설정이 없는 경우, 샤드에 골고루 분산 저장됨
3. 데이터 타입
keyword
- 문자열 타입
-
분석기를 거치지 않고 원문 그대로 색인
-
정형화 된 컨텐츠에 사용
-
검색 시 필터링되는 항목
-
정렬 기능(Sorting)이 필요한 항목
-
집계 기능(Aggregation)을 사용해야 하는 항목
text
- 문자열 타입
-
지정한 분석기(미지정시 Standard Analyzer)를 거쳐 색인
-
전문 검색 가능 (포함된 특정 단어 검색 가능)
-
정렬/집계 기능을 사용해야 할 경우 Text 타입과 Keyword 타입을 동시에 설정 가능(멀티 필드)
Array
하나의 필드에 여러 데이터가 들어가는 경우 사용 (OR 연산)
# Example
PUT goods_sample/_doc
{
"goodsNm" : "갤럭시 Z플립",
"vendor" : "Samsung",
"colour" : ["gold", "black", "purple"]
}
Numeric
데이터 크기별 숫자 데이터 타입 제공
- long
- integer
- short
- byte
- double
- float
- half_float
Date
JSON 포맷에서 문자열 처리되며 포매팅 설정 가능
# Example
PUT goods_sample/_mapping/_doc
{
"properties" : {
"orderDate" : {
"type" : "date",
"format" : "yyyy-MM-dd HH:mm:ss"
}
}
}
Range
범위가 있는 데이터가 인입되는 경우 사용
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
# Example
## deliveryPeriod 필드 타입을 date_range로 설정
PUT goods_sample/_mapping/_doc
{
"properties" : {
"deliveryPeriod" : {
"type" : "date_range",
"format" : "yyyy-MM-dd"
}
}
}
## 2020-03-02 ~ 2020-03-06
PUT goods_sample/_doc/1
{
"deliveryPeriod" : {
"gte" : "2020-03-02",
"lte" : "2020-03-06"
}
}
Boolean
참/거짓 논리값
- true, "true"
- false, "false"
# Example
## delivered 필드 타입을 boolean으로 설정
PUT goods_sample/_mapping/_doc
{
"properties" : {
"delivered" : {
"type" : "boolean"
}
}
}
PUT goods_sample/_doc/1
{
"delivered" : true
}
Geo-Point
-
위도, 경도 등 위치 정보를 담은 데이터를 저장할 경우 사용
-
위치 기반 쿼리를 이용해 반경 내 쿼리, 위치 기반 집계, 위치별 정렬 등을 사용할 수 있음
-
해당 필드 타입을 geo_point로 매핑 후, 해당 값에 lat(위도; latitud)와 lon(경도; longitude)값을 지정
IP
IPv4, IPv6 모두 가능
다음 이야기 : [Elasticsearch] - 4. 엘라스틱서치 분석기
본 글은 다음을 참고하여 작성되었습니다.
권택환 외, 엘라스틱서치 실무가이드, 위키북스
'KR > 검색' 카테고리의 다른 글
[Elasticsearch] - 5. 커스텀 분석기 (0) | 2020.03.23 |
---|---|
[Elasticsearch] - 4. 엘라스틱서치 분석기 (0) | 2020.03.23 |
[Elasticsearch] - 2. 엘라스틱서치의 이해 (2) (0) | 2020.03.23 |
[Elasticsearch] - 1. 엘라스틱서치의 이해 (1) (2) | 2020.03.23 |
[데이터 색인] 역색인 구조 (역 인덱스; Inverted Index) (2) | 2020.03.15 |