본문 바로가기
도서기록/Elasticsearch In Action

4장 매핑

by 코엘리 2025. 5. 30.
반응형

4.1 매핑 개요

4.1.1 매핑 정의

  • 매핑은 도큐먼트의 데이터 필드 및 관련 데이터 타입을 나타내는 스키마를 정의하고 개선하는 과정이다.
  • 일래스틱 서치는 도큐먼트를 인덱싱하는 동안 필드의 데이터 타입을 이해하고 데이터 검색을 위해 필드를 적절한 데이터 구조에 저장한다.

4.1.2 첫 도큐먼트 인덱스 생성(스키마 생성하지 않고 도큐먼트 인덱싱)

PUT movies/_doc/1
{
  "title":"Godfather",
  "rating":4.9,
  "release_year":"1972/08/01"
}
  1. 기본 설정으로 새 인덱스(movies) 가 생성된다.
  2. 추론된 데이터 타입을 사용해 movies 인덱스에 대한 새 스키마를 생성한다. -> 동적 매핑
  3. 도큐먼트는 인덱싱되어 일래스틱 서치 데이터 저장소에 저장된다.
  4. 일래스틱 서치는 추가 인덱싱을 위해 새로 생성된 스키마를 참조하므로, 후속 도큐먼트는 이전 단계를 거치지 않고 인덱스 된다.

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 프로세스

  1. 업데이트 된 스키마 정의로 새 인덱스 생성
  2. reindex API 로 이전 인덱스 데이터를 새 인덱스로 복사.
  3. 새 인덱스가 준비되면 애플리케이션이 해당 인덱스로 전환한다.
  4. 새 인덱스 작동 확인 후 이전 인덱스 삭제
POST _reindex
{
  "source": {"index": "orders"},
  "dest": {"index": "orders_new"}
}

4.3.4 타입 강제

  • 스키마 정의시 필드를 integer 타입으로 정의하고, 인덱싱 요청 시 문자열로 입력되었다고 가정해보자.
    • 이 때, 일래스틱 서치는 오류를 방지하기 위해 타입 변환을 강제한다.

4.4 데이터 타입

  1. 단순 타입: 문자열, 날짜, 숫자 등 기본 데이터 변형
    • text, boolean, long, date, double, binary
  2. 복합 타입: 객체가 내부 객체를 보유할 수 있는 프로그래밍 언어의 객체 구성
    • object, nested, flattened, join
  3. 특수 타입: 지리적 위치 또는 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