반응형
4.1 매핑 개요
4.1.1 매핑 정의
- 매핑은 도큐먼트의 데이터 필드 및 관련 데이터 타입을 나타내는 스키마를 정의하고 개선하는 과정이다.
- 일래스틱 서치는 도큐먼트를 인덱싱하는 동안 필드의 데이터 타입을 이해하고 데이터 검색을 위해 필드를 적절한 데이터 구조에 저장한다.
4.1.2 첫 도큐먼트 인덱스 생성(스키마 생성하지 않고 도큐먼트 인덱싱)
PUT movies/_doc/1
{
"title":"Godfather",
"rating":4.9,
"release_year":"1972/08/01"
}
- 기본 설정으로 새 인덱스(movies) 가 생성된다.
- 추론된 데이터 타입을 사용해 movies 인덱스에 대한 새 스키마를 생성한다. -> 동적 매핑
- 도큐먼트는 인덱싱되어 일래스틱 서치 데이터 저장소에 저장된다.
- 일래스틱 서치는 추가 인덱싱을 위해 새로 생성된 스키마를 참조하므로, 후속 도큐먼트는 이전 단계를 거치지 않고 인덱스 된다.
4.2 동적 맵핑
- 스키마가 없으면 매핑과 인덱스가 모두 자동으로 생성된다.
4.2.1 타입 추론 메커니즘
일래스틱서치는 필드 값을 분석하고 해당 값을 기반으로 동등한 데이터 타입을 추론한다.
추론은 대부분 적합하지만, 기본 트랙에서 약간 벗어난 경우 부족할 수 있다.
- 예 1) date 필드로 원하는 값이 ddMMyyyy 와 같은 일반적인 형식이 아닌 경우 동적 매핑을 사용할 수 없음
- 예 2) long 필드 값에 첫 인덱싱을 소수점이 아닌 정수 타입을 넣을 경우, "float" 대신 "long" 타입으로 배정될 수 있음.
일래스틱 서치가 알아서 스키마를 만들도록 허용하지 않는 것이, 잘못된 스키마 정의를 막을 수 있다.
4.2.2 동적 맵핑 한계
잘못된 맵핑 도출
- 숫자 필드가 문자열로 래핑되어 "3.14"와 같은 값을 가지는 경우 float또는 double 이 아닌 text 로 자동 매핑된다.
- 일래스틱 서치는 정렬 작업에서 text 필드를 사용할 수 없어서 오류가 발생할 수 있다.
- text 필드를 정렬하려면, 스키마를 정의할 때 fielddata 를 true 로 설정하면 된다.
- 그러나, fielddata는 데이터 매시의 클러스터 힙 메모리에 저장되어 성능에 좋지 않다.
- fielddata를 활성화하는 것보다 keyword 필드를 사용하는 것이 좋다.
keyword 타입을 사용한 정렬 수정
- 일래스틱 서치는 기본적으로 keyword를 두 번째 타입으로 사용해 모든 필드를 다중 필드로 사용할 수 있다.
- keyword 타입 필드는 정렬함수를 적용할 수 있다.
- 예)
GET students_temp/_search
{
"sort": [
{
"age.keyword": {
"order": "asc"
}
}
]
}
잘못된 날짜 형식 파생
- 날짜가 아닌 데이터 타입은 날짜 계산을 수행할 수 없다.
- 따라서 명시적 매핑을 사용하자
4.3 명시적 매핑
4.3.1 인덱싱 API 를 사용한 매핑
- 인덱스 생성 시 매핑 정의 생성
PUT <index_name>
{
"mappings": {
"properties":{
"field_name": {
"type": "data_type",
"param": "param_value",
}
"field_name2": {...} // 두 번째 필드 이름
}
}
}
4.3.2 매핑 API 를 사용한 스키마 업데이트
- 추가 필드를 사용해 기존 데이터 스키마 정의를 수정한다.
PUT employees/_mapping
{
"properties":{
"joining_date":{
"type":"date",
"format":"dd-mm-yyyy"
},
"phone_number":{
"type":"keyword"
}
}
}
빈 인덱스 업데이트
- 빈 인덱스 생성 후 _mapping 엔드포인트 호출하여 스키마를 생성할 수 있다.
4.3.3 기존 필드 수정은 허용되지 않는다.
- 인덱스가 라이브(데이터 필드가 생성되고 작동중인)가 되면, 인덱스 기존 필드에 대한 수정이 금지된다.
- 데이터 타입 수정을 위해서는 재인덱싱(reindex)을 사용해야 한다.
reindex 프로세스
- 업데이트 된 스키마 정의로 새 인덱스 생성
- reindex API 로 이전 인덱스 데이터를 새 인덱스로 복사.
- 새 인덱스가 준비되면 애플리케이션이 해당 인덱스로 전환한다.
- 새 인덱스 작동 확인 후 이전 인덱스 삭제
POST _reindex
{
"source": {"index": "orders"},
"dest": {"index": "orders_new"}
}
4.3.4 타입 강제
- 스키마 정의시 필드를 integer 타입으로 정의하고, 인덱싱 요청 시 문자열로 입력되었다고 가정해보자.
- 이 때, 일래스틱 서치는 오류를 방지하기 위해 타입 변환을 강제한다.
4.4 데이터 타입
- 단순 타입: 문자열, 날짜, 숫자 등 기본 데이터 변형
- text, boolean, long, date, double, binary
- 복합 타입: 객체가 내부 객체를 보유할 수 있는 프로그래밍 언어의 객체 구성
- object, nested, flattened, join
- 특수 타입: 지리적 위치 또는 IP 주소 등
- geo_shape, geo_point, it ...
4.5 핵심 데이터 타입
4.5.1 text
text
- text 데이터 타입은 저장 전 모두 분석된다.
- 구조화되지 않은 텍스트는 토큰 분할, 문자 필터링, 어근 축소(stemmed), 동의어 추가, 자연어 처리 규칙 적용 등의 분석 프로세스를 거친다.
token_count
- 텍스트 데이터 타입의 특수한 형식
- 해당 필드의 토큰 수를 캡처하는 필드를 정의한다.
PUT tech_books
{
"mappings": {
"properties": {
"title": {
"type": "token_count", // title 의 데이터 타입
"analyzer": "standard" // 이 분석기 제공
}
}
}
}
#Insert some adhoc docs:
PUT tech_books/_doc/1
{
"title":"Elasticsearch in Action"
}
PUT tech_books/_doc/2
{
"title":"Elasticsearch for Java Developers"
}
PUT tech_books/_doc/3
{
"title":"Elastic Stack in Action"
}
#Finally, let's put the token_count to use:
# title의 단어 수 기준으로 책을 가져온다.
GET tech_books/_search
{
"query": {
"range": {
"title": {
"gt": 3,
"lte": 5
}
}
}
}
- title 필드를 text 타입과 token_count 결합으로 사용할 수도 있다.
PUT tech_books
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"word_count": {
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
}
- 결합 후 term 쿼리(구조화된 데이터 질의) 실행
GET tech_books/_search
{
"query": {
"term": {
"title.word_count": {
"value": 4
}
}
}
}
4.5.2 keyword 데이터 타입
keyword
- keyword 데이터 타입은 필드를 있는 그대로 유지한다.
- 해당 필드가 토큰화되지 않고 분석되지도 않는다.
- 관련성 점수는 필요치 않으며, 이진 출력을 제공함
constant_keyword
- 해당 인덱스의 모든 도큐먼트에 대해 정확히 동일한 값을 갖는다.
whildcard
- whildcard와 정규식을 사용한 데이터 검색 지원
4.5.3 date 데이터 타입
- 필요에 따라 날짜 형식을 사용자가 지정할 수 있음
{
"mappings": {
"properties": {
"departure_date_time":{
"type": "date",
"format": "dd-MM-yyyy||dd-MM-yy"
}
}
}
}
4.6 고급 데이터 타입
4.6.1 geo_point 데이터 타입
PUT restaurants
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"address":{
"type": "geo_point"
}
}
}
}
## 인덱싱
PUT restaurants/_doc/1
{
"name":"Sticky Fingers",
"address":{
"lon":"0.1278",
"lat":"51.5074"
}
}
## 쿼리 질의 with geo_bounding_box
GET restaurants/_search
{
"query": {
"geo_bounding_box":{
"address":{
"top_left":{
"lon":"0",
"lat":"52"
},
"bottom_right":{
"lon":"1",
"lat":"50"
}
}
}
}
}
4.6.2 object 데이터 타입
- 속성을 갖는 내부 객체를 표현하기 위한 타입
- object 타입은 인덱싱 될 때 개별 도큐먼트로 저장되지 않고 평탄화되기 때문에 검색 시 에러가 날 수 있다.
- 예를들어, 아래와 같다
## 인덱싱
PUT emails/_doc/2
{
"to:":"mrs.doe@johndoe.com",
"subject":"Multi attachments test",
"attachments":[{
"filename":"file2.txt",
"filetype":"confidential"
},{
"filename":"file3.txt",
"filetype":"private"
}]
}
## 데이터는 아래처럼 저장됨
{
...
"attachments.filename": ["file2.txt", "file3.txt"],
"attachments.filetype": ["private", "confidential"]
}
## 질의
GET myemails/_search
{
"query": {
"bool": {
"must": [
{"term": { "attachments.filename.keyword": "file2.txt"}},
{"term": { "attachments.filetype.keyword": "private" }}
]
}
}
}
## 모든 데이터가 반환되지만, 찾고자 하는 데이터가 아님
4.6.3 nested 데이터 타입
- 도큐먼트에 있는 객체 배열 간 관계를 유지하는 특수 형태 object
- 연관 및 관계를 존중하는데 적합함.
- 각 객체를 개별 객체로 처리하는 객체 배열을 만들 경우 적합함.
## 스키마 설정
PUT emails_nested
{
"mappings": {
"properties": {
"attachments": {
"type": "nested",
"properties": {
"filename": {
"type": "keyword"
},
"filetype": {
"type": "text"
}
}
}
}
}
}
## 인덱싱
PUT emails_nested/_doc/1
{
"attachments" : [
{
"filename" : "file1.txt",
"filetype" : "confidential"
},
{
"filename" : "file2.txt",
"filetype" : "private"
}
]
}
## 검색
GET emails_nested/_search
{
"query": {
"nested": {
"path": "attachments",
"query": {
"bool": {
"must": [
{ "match": { "attachments.filename": "file1.txt" }},
{ "match": { "attachments.filetype": "private" }}
]
}
}
}
}
}
4.6.4 flattened 데이터 타입
- 하나 이상의 하위 필드 형태로 정보를 보유하며 각 하위 필드 값은 keyword로 인덱싱된다.
- 텍스트 분석 프로세스를 거치지 않는다.
## 스키마 정의
PUT consultations
{
"mappings": {
"properties": {
"patient_name":{
"type": "text"
},
"doctor_notes":{
"type": "flattened"
}
}
}
}
## 인덱싱
PUT consultations/_doc/1
{
"patient_name":"John Doe",
"doctor_notes":{ ## 여러 하위 필드로 구성 가능
"temperature":103,
"symptoms":["chills","fever","headache"],
"history":"none",
"medication":["Antibiotics","Paracetamol"]
}
}
## 검색
GET consultations/_search
{
"query": {
"match": {
"doctor_notes": "Paracetamol"
}
}
}
4.6.5 join data type
- 일반적으로 사용되지 않지만, 관계 유지 등 관리할 때 도움이 되는 경우 사용하여 부모-자식 관계를 사용할 수 있음
4.6.6 search_as_you_type
- 이 데이터 타입의 필드는 일래스틱서치는 사용자 검색과 부분적으로 일치하는 n-gram 이라는 하위집합을 생성한다.
- 검색은 기본 필드와 하위 필드에서 진행되어야 하므로 multi_match 쿼리를 생성한다.
GET tech_books4/_search
{
"query": {
"multi_match": {
"query": "in",
"type": "bool_prefix",
"fields": ["title","title._2gram","title._3gram"]
}
}
}
4.7 다중 데이터 타입 필드
기본 필드 정의 내 fields 객체를 사용해 스키마 정의에 여러 타입을 생성할 수 있다.
## 예시
PUT emails
{
"mappings": {
"properties": {
"subject":{
"type": "text",
"fields": {
"kw":{ "type":"keyword" },
"comp":{ "type":"completion" }
}
}
}
}
}
- 검색 시 subject.kw, subject.comp 와 같이 검색한다.
반응형
'도서기록 > Elasticsearch In Action' 카테고리의 다른 글
2장 시작해보기 (1) | 2025.05.11 |
---|