ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [ElasticSearch 엘라스틱서치] 멀티 필드 맵핑, 정렬과 검색을 동시에
    [IT] 공부하는 개발자/Open Source 2019. 8. 21. 00:45

    엘라스틱서치, Mapping?

    엘라스틱서치 안에서 맵핑이란, 사용될 필드들의 타입(자료형)을 사전에 정의해주는 것이다. 관계형 데이터베이스로 비유하자면 스키마 정의와 같다. 텍스트 타입 이외에도 다양한 숫자 타입, 날짜 타입, 위치 데이터 등으로 정의할 수 있으며 디테일한 커스텀 설정이 가능하다. 이 포스팅은 맵핑안에서 "fields" 파라미터를 이용하여, 한 필드가 다양한 특성을 동시에 가질 수 있도록 커스텀 맵핑하는 법에 대해 설명한다.

     


     

    1. 맵핑 기본문법 SYNTAX

    # MAPPING

    PUT /my-index
    {
      "mappings": {
        "properties": {
          "age":    { "type": "integer" },  
          "email":  { "type": "keyword"  }, 
          "name":   { "type": "text"  }     
        }
      }
    }

    my-index 라는 인덱스에 사용될 필드들을 맵핑하였다. age 필드는 integer 타입, email 필드는 keyword 타입, name 필드는 text를 가지도록 맵핑한다.

     


     

    # UPDATE

    PUT /my-index/_mapping
    {
      "properties": {
        "employee-id": {
          "type": "keyword",
          "index": false
        }
      }
    }

    기존의 index에 새로운 필드 맵핑을 추가할수도 있다. employee-id 라는 keyword 타입의 필드을 새로 정의하였다.
    단, 이미 정의된 필드의 경우, 타입 변경은 불가능하고 "fields" (이 포스팅에서 설명할 멀티 필드 기능) / "ignore_above" 파라미터를 수정하는 경우에 한해서만 허용된다. 



    # VIEW

    GET /my-index/_mapping

    정의된 맵핑을 조회하는 쿼리이다. 예상되는 리턴은 아래와 같다.

    {
      "my-index" : {
        "mappings" : {
          "properties" : {
            "age" : {
              "type" : "integer"
            },
            "email" : {
              "type" : "keyword"
            },
            "employee-id" : {
              "type" : "keyword",
              "index" : false
            },
            "name" : {
              "type" : "text"
            }
          }
        }
      }
    }

     


     

     

     

    2. 필드 데이터 타입

    TYPE 구분 타입
    단순형 (SIMPLE TYPE) TEXT: 풀 텍스트 (상품 설명, 질문 답변)
    KEYWORD: 인덱스화되어있는 키워드타입의 데이터 (예시: 이메일주소, 우편번호)
    DATE: 날짜형, LONG: 숫자형, DOUBLE: 숫자형, BOOLEAN: 바이너리, IP
    계급형 (HIERARCHICAL TYPE) OBJECT, NESTED
    특수형 (SPECIALISED TYPE) GEO_POINT, GEO_SHAPE, COMPLETION

    다양한 타입으로 정의할 수 있다 (참조)


     

     

     

    3. 멀티 필드 맵핑

    멀티 필드 맵핑의 활용법

    - 특정 필드에 풀 텍스트 검색 & 정렬 등을 동시에 사용하고 싶을 때

    - 특정 필드에 여러 가지 분석기(Analyzer)를 적용하고 싶을 때

     

    멀티 필드 맵핑은, 엘라스틱 서치 안에서 동일한 필드를 다른 용도로 사용하고자 할 때에 무척 유용하다. 예를 들어 '상품 이름' 이라는 항목에 analyzer도 사용하고 싶고, 동시에 클러스터링이나 정렬도 사용하고 싶다면 난감할 수 있다. 키워드 필드 데이터에는 analyzer를 사용할 수 없고, text 형 데이터는 정렬기능이 지원되지 않기 때문이다. 두 가지 특성을 모두 사용할 수 없을까? 이 경우는 "fields" 파라미터를 추가해, 멀티 맵핑을 하면 된다.


     

     

    멀티 필드 맵핑 쿼리

    PUT my_index
    {
      "mappings": {
        "properties": {
          "city": {
            "type": "text",
            "analyzer": "english"
            "fields": {
              "raw": { 
                "type":  "keyword"
                "normalizer": "custom_normalizer"
              }
            }
          }
        }
      }
    }

    city 라는 이름의 데이터 타입을 정의하였다. 기본 타입은 text 타입에, english 분석기를 사용하도록 했다. 그리고 fields 파라미터로 "raw" 라는 자식을 따로 정의하였다. 자식 필드는 keyword 타입에, custom_normalizer 라는 노멀라이저를 사용한다. (*분석기가 텍스트 타입에만 사용가능한 반면, 노멀라이저는 키워드 타입에 사용할 수 있고, 성능은 거의 동일한데 노멀라이즈는 단일화 토큰을 생성한다. 자세한 것은 링크 참조) 

     

     

    맵핑 후 테스트 데이터 삽입

    PUT my_index/_doc/1
    {
      "city": "New York"
    }
    
    PUT my_index/_doc/2
    {
      "city": "York"
    }
    

    city 필드에 "New York", "York"라는 데이터 2개를 삽입하였다. 

     

     

    검색 쿼리

    GET my_index/_search
    {
      "query": {
        "match": {
          "city": "york" 
        }
      },
      "sort": {
        "city.raw": "asc" 
      },
      "aggs": {
        "Cities": {
          "terms": {
            "field": "city.raw" 
          }
        }
      }
    }

    city는 멀티 필드 맵핑에 의해서, 분석기가 적용된 text 타입과 노멀라이저가 적용된 keyword 타입 양 쪽 모두 가지므로 검색, 정렬, 클러스터링에 동시에 사용될 수 있다. 검색쿼리의 타겟은 "city" 필드가(text 타입) 타겟이 되고, 정렬과 클러스터링 쿼리는 "city.raw"(keyword 타입) 필드가 타겟이 된다. 


     

     

     

     

    기타

     

    - 하위 노드의 명칭은 편의에 따라 raw 이외의 이름으로 변경할수도 있다. 

    댓글

Copyright in 2020 (And Beyond)