-
엘라스틱서치 인덱스 매핑카테고리 없음 2024. 2. 12. 21:38
매핑 : 문서가 인덱스에 어떻게 색인되고 저장되는지를 정의
-> JSON의 각 필드를 어떻게 분석하고 색인할지 어떤 타입으로 저장할지 등을 세부적으로 지정할 수 있음
이 전 글에서 생성한 인덱스에 문서를 색인한 후 인덱스를 다시 확인해보자
인덱스에 문서를 색인 mapping 데이터가 존재 -> mapping 데이터에 필드의 타입과 관련된 정보가 생성된걸 확인할 수 있음 ( 동적 매핑 )
-> 기존 mapping 데이터가 존재하지 않으면 엘라스틱서치는 자동으로 적당한 필드 타입을 지정하고 mapping 정보를 생성한다.
-> PUT 인덱스이름 { "mapping": { "properties": {...}}} 명령을 통해 명시적 매핑이 가능하다.
-> 매핑 설정 필드 타입은 한번 지정되면 변경이 불가능
-> 매핑을 어떻게 지정하느냐에 따라 성능차 발생
필드 타입
- 심플 타입 : text, keyword, date, long, double, boolean ...
- 간단한 자료형
- text, keyword 타입은 매우 중요
- 부동소수점을 담는 필드라면 환산 계수로 스케일링해서 정수로 저장하는 scaled_float 타입을 고려할 수 있음
- scaling_factor라는 변수를 지정해야한다.
- scaling_factor를 100으로 지정하고 값이 1.234라면 엘라스틱서치는 이 값을 123으로 색인한다.
- date 타입은 epoch miliseconds형식과 format이 적용된 문자열 형식 모두 저장및 검색할 수 있다.
- 여러 형식을 지원하려면 format을 || 문자로 이어 붙이면 된다.
- long 타입필드는 숫자 데이터를 넣을 수 있고 숫자로 이뤄진 배열을 넣을 수 있다.
- 배열 데이터의 타입이 다른 경우 색인은 실패한다.
- 필드를 query term 으로 검색하는 경우 배열에 속한 숫자와 배열이 아닌 수자 모두를 검색한다.
- 색인 과정에서 독립적인 역색인을 구성하기 때문에 가능
배열이 아닐때 배열일 때 - 계층 구조를 지원하는 타입 : object, nested
-> object, nested 두 타입은 유사하나 배열을 처리할 때 동작이 다르다.
object 타입
테스트 데이터 삽입 (1)
PUT object_test/_doc/1 { "price": 3000.55, "spec": { "name": "엘라스틱서치", "content": "엘라스틱 서치 검색 최고", "user_score": 4.5 } }
위 object는 내부적으로 아래와 같은 키-값 쌍으로 색인된다.
{ "price": 3000.55, "spec.name": "엘라스틱서치", "spec.content": "엘라스틱 서치 검색 최고", "spec.user_score": 4.5 }
테스트 데이터 삽입 (2)
PUT object_test/_doc/2 { "spec":[ { "name": "test-name-1", "content": "test-content-1", "user_score": 4 }, { "name": "test-name-2", "content": "test-content-2", "user_score": 1 }, { "name": "test-name-3", "content": "test-content-3", "user_score": 5 } ] }
위 데이터는 내부적으로 아래처럼 저장된다.
{ "spec.name": ["test-name-1", "test-name-2", "test-name-3"], "spec.content": ["test-content-1","test-content-2","test-content-3"], "spec.user_score": [4, 1, 5] }
-> 위 데이터처럼 저장되기 때문에 name="test-name-1", "content" = "test-content-3"와 같은 조건으로 만족하는 객체는 존재하지 않지만 위 데이터가 검색결과에 잡히게 된다.
->object 타입은 배열을 구성하는 객체를 독립적인 데이터로 취급하지 않는다.
nested 타입
먼저 인덱스를 생성할 때 타입을 "nested"라고 지정한다.
PUT nested_test/_doc/1 { "mappings": { "properties": { "spec": { "type": "nested", "properties": { "name": { "type": "text" }, "content": { "type": "text" }, "user_store": { "type": "long" } } } } } }
그 후 생성한 인덱스에 데이터를 삽입한다.
{ "spec":[ { "name": "test-name-1", "content": "test-content-1", "user_score": 4 }, { "name": "test-name-2", "content": "test-content-2", "user_score": 1 }, { "name": "test-name-3", "content": "test-content-3", "user_score": 5 } ] }
-> 위 와 같은 테스트 환경을 생성한 후 다시 name= "test-name-1", content=""test-content-2"를 검색하면 검색 결과가 노출되지 않는다.
-> 하지만 name="test-name-1", content="test-content-1"로 변경하여 검색하면 결과가 나올 것으로 예상하지만 그렇지 않다.
-> nested 타입은 매우 특수한 타입으로 배열의 부모와 배열의 각 요소를 문서화하여 내부적으로 저장하기 때문에 nested 쿼리를 사용해서 검색해야한다.
- 내부적으로 객체를 별도의 문서로 분리해서 저장하기 때문에 성능 문제가 발생
- 인덱스 설정 mapping.nested.fields.limit 옵션 통해 한 인덱스에 nested 타입을 몇 개까지 설정할 수 있는지를 제한할 수 있다.
- 인덱스 설정 mapping.nested_objects.limit 옵션 통해 한 문서가 nested 객체를 몇 개까지 가질 수 있는지를 제한
nested 쿼리 문법
GET 인덱스이름/_search { "query":{ "nested": { "path": "spec" // 검색 필드 이름 "query": { ... } } } }
- 특수 타입 : geo_point, geo_shape ...
- geo_point : 위도, 경도를 저장하는 타입
- geo_shape : 지도상의 특정 지점, 선, 도형 등을 표현하는 타입
- binary : base64로 인코딩된 문자열을 저장하는 타입
- completion : 자동완성 검색을 위한 특수 타입