엘라스틱서치의 분석(analysis)은 텍스트 필드만 대상으로 한다고 했어요. 그럼 누가 '이 필드는 텍스트 필드예요.', '이 필드는 숫자형 필드예요.'라고 알려주는 걸까요? 엘라스틱서치는 뭘 보고 어떤 필드가 어떤 데이터 형을 사용하는지 알 수 있을까요?
엘라스틱서치에서 사상(寫像) - Mapping
엘라스틱서치 공식문서에서는 매핑을 도큐먼트와 그 안에 있는 필드들이 엘라스틱서치 안에 어떻게 색인되고 저장되는지를 정의하는 작업이라고 설명하고 있어요. 매핑이란 우리말로 사상(寫像)이라고 하는데 수학에서든 컴싸에서든 둘 사이 어떤 관계를 만드는 것 혹은 연결하는 것을 사상 혹은 매핑이라고 해요.
그러니까 엘라스틱서치 애널리시스는 인덱스에 도큐먼트가 생성될 때 어떤 필드는 어떤 형식의 데이터이니 어떠한 구조로 저장해야겠다. 라고 하는 것을 정의 해 놓은 것이 엘라스틱서치의 매핑이에요.
DB에서 테이블을 만들기 전에 혹은 프로그래밍에서 클라스를 정의하기 전에 이 테이블은, 이 클라스는 어떤 형식의 데이터를 무슨 이름으로 저장할지 설계도 같은 걸 그리는데 MySQL과 엘라스틱서치를 비교해 보면 이렇게 될 거 같아요.
자 그럼 엘라스틱서치에서 매핑을 만드는 방법에 대해서 알아봐요.
엘라스틱서치에서 매핑을 만드는 방법은 두가지가 있어요.
- 동적 매핑(Dynamic mapping) - 인덱스에 처음 생성되는 필드의 값을 보고 자동으로 매핑을 생성해준다.
동적 매핑은 이미 사용해본 적이 있어요. 위에 보는 이게 books 인덱스의 매핑이에요.{ "books" : { "mappings" : { "properties" : { "in_stock" : { "type" : "long" }, "price" : { "type" : "float" }, "rating" : { "type" : "float" }, "title" : { "type" : "text", "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 }}}}}}}
재고는 long으로 가격은 float으로,, 이런 걸 만들어준 기억이 없는데 어떻게 생성되어있을까요?
이렇게 엘라스틱서치는 친절하게 자동으로 매핑을 생성해줘요. 이게 동적 매핑이에요. - 명시적 매핑(Explicit mapping) - 인덱스에게 어떤 필드에 어떤 자료형이 들어올지 수동으로 생성해준다.
아직 exp-mapping이라는 인덱스가 없어요. PUT /exp-mapping 요청을 보내서 인덱스를 생성하고 그 인덱스 내용을 확인하면 이렇게 매핑 필드가 비어있는 것을 볼 수 있어요
그리고 아래는 인덱스에 mappings라는 필드에 title은 키워드형으로 desc는 텍스트 형으로 데이터를 인덱싱하고 저장하라는 매핑을 만들어주는 요청이에요."exp-mapping" : { "aliases" : { }, "mappings" : { }, "settings" : { ...
이렇게 요청을 보내고 다시 확인해보면 매핑 필드에 요청한 대로 title은 키워드 형으로 desc는 텍스트 형으로 매핑이 생성된 걸 볼 수 있어요.PUT /exp-mapping { "mappings": { "properties": { "title": { "type": "keyword" }, "desc": { "type": "text" }}}}
자료형 - Data Type
몇몇 자료형을 제외하면 엘라스틱서치에서의 자료형은 여러 프로그래밍 언어나 DBMS에서 사용되는 자료형과 크게 다르지 않아요.
float, integer, date, text, object 등은 친숙한 데이터 타입일 것 같아요 엘라스틱서치에서는 이런 데이터 타입 외에 특별한 데이터 타입을 가지고 있어요. 예를 들어 IP 주소를 저장하는 자료형 IP, 위치 정보를 저장하는 자료형 Geopoint, 아래 링크에서는 엘라스틱서치 매핑에 사용되는 필드 데이터 타입의 종류와 간단한 소개를 하고 있어요
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
Field data types | Elasticsearch Guide [7.14] | Elastic
Each field has a field data type, or field type. This type indicates the kind of data the field contains, such as strings or boolean values, and its intended use. For example, you can index strings to both text and keyword fields. However, text field value
www.elastic.co
다른 데이터 타입은 차차 알아보도록 하고 오늘은 오브젝트 형 데이터 타입에 대해 조금 알아볼게요. 지금까지 해리포터 시리즈를 도큐먼트로 저장해왔는데 책 제목과 별점 등은 입력했지만 저자는 아직 입력하지 않았었잖아요? 저자를 오브젝트 형으로 입력하는 방법을 확인해볼게요. 오브젝트형 데이터 타입은 아래와 같이 만들 수 있어요.
POST /books/_update/AlzywnsBDZxsqjhBZSWk
{
"doc": {
"author": {
"first_name": "Joanne",
"last_name": "Rowling"
}}}}
먼저 해리포터와 마법사의 돌 도큐먼트를 업데이트 API를 통해서 저자 필드를 추가했어요. 이름은 조앤, 성은 롤링으로 입력을 했어요. 그리고 books의 매핑이 어떻게 변했는지 한 번 볼게요.

athour필드는 first_name과 last_name이라는 필드를 properties라는 키가 감싸고 있는 모양으로 생겼네요. 매핑을 만들 때도 마찬가지로 내가 어떤 필드를 오브젝트 형으로 만들고 싶다 하면 properties 키를 활용해서 그 안에 들어갈 필드들을 묶어주면 돼요. 문제는 여기서부터에요 Apache Lucene에는 오브젝트형이라는 자료형은 없어요. 그럼 Shards에는 어떻게 오브젝트형이 저장될까요?
엘라스틱서치는 오브젝트형 데이터를 Apache Lucene이 알아볼 수 있게 변환해서 인덱싱 해요. 그래서 최종적으로는
author.first_name: joanne
author.last_name: rowling
이런 형식으로 저장되게 돼요.
그럼 여기서 한 발 더 나아가서 오브젝트 형 배열은 어떻게 될까요? 해리포터와 마법사의 돌에 reviews라는 필드를 오브젝트형 배열로 넣고 안에 3개의 리뷰를 넣어볼게요.
POST /books/_update/AlzywnsBDZxsqjhBZSWk
{
"doc": {
"reviews": [
{
"rating": 5.0,
"reviewer": "John Doe",
"desc": "Perfect!!"
},
{
"rating": 4.0,
"reviewer": "Jane Smith",
"desc": "Good"
},
{
"rating": 3.0,
"reviewer": "Jane Roe",
"desc": "Not bad"
}]}}
그리고 이 books 안에서 reviews.rating이 4.0 이상만 얻어올 수 있을까요? 바로 답을 알려드리자면 없어요. 그럴 수 없어요. 왜냐하면 어떻게 저장되었는지를 생각해보면 돼요.
이 reviews라는 필드는 엘라스틱서치에 의해서
reviews.rating: [5.0, 4.0, 3.0],
reviews.reviewer: ["John Doe", "Jane Smith", "Jane Roe"],
reviews.desc: ["Perfect", "Good", "Not bad"]
이런 식으로 플래튼 되어서 저장될 거예요 그리고 각 리뷰의 점수와 리뷰어, 설명 등의 상관관계는 없어질 거예요.

이렇게 친절하게 나와있어요.
오늘은 오브젝트 자료형을 배열 형식으로 저장하면 어떤 문제점이 발생할 수 있구나 하는 정도로 마무리를 하고 엘라스틱서치에서는 어떤 자료형을 사용하는지에 대해서만 다시 한번 보고 넘어가면 좋을 것 같아요.
그럼 오늘은 여기까지.