top bar

글 목록

2017년 8월 13일 일요일

[Elasticsearch] 문자열 Data Type과 Analyze


Elasticsearch 인덱스의 mapping 설정시 각 field의 '타입'을 정하게 되는데,
우리가 흔히 다루는 문자열에 관한 타입은 'keyword'와 'text'가 있다.
이제부터 문자열 타입에 관해 정리 하겠다.

INFO: 2.x 버전의 elasticsearch에서 문자열은 'string' type 하나만 지원 했지만, 5.x 버전부터 해당 타입은 제거 되었다.


Keyword datatype



정형화된 문자열 컨텐츠 (예를 들어 이메일 주소, 호스트 이름, 각종 상태코드, 우편번호 등등..) 를 색인할 경우엔 해당 필드에 'keyword' 타입을 적용한다. 해당 타입의 필드는 일반적으로 아래와 같은 경우에 사용하게 된다.

  • 검색 시 Filtering
  • Sorting
  • Aggregation

다만 'keyword' 타입의 필드는 'Analyze' 되지 않기 때문에, 문자열 값 자체로만 검색 할 수 있다. 예를들어, 'Hello World' 라는 문자열이 색인됬다고 가정했을때, 'Hello'나 'World' 만으로는 해당 문서를 검색할 수 없는 식이다.

아래와 같이 설정 한다.

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "my_keyword_field": {
          "type": "keyword"
        }
      }
    }
  }
}



Text datatype



전문(full text) 형식과 같은 문자열 (예를들어 메일 본문과 같은) 을 색인 할 때는 필드에 'text' 타입을 적용한다. 해당 타입으로 설정된 필드는 기본적으로 'analyzed' 속성이며, 'Analyzer'를 통해서 문자열이 각각 분리된 토큰으로 인덱스에 색인 된다. 따라서 메일 본문과 같이 큰 문자열 덩어리를 가지고 있는 document를 그 본문안의 각각 단어로 검색 할 수 있게 해 준다. (이른바 'Full Text Search'..)

다만 해당 필드를 'sorting' 작업에 사용할 경우, 메모리 점유와 성능 문제를 가져온다. 때문에 sorting 작업엔 거의 사용하지 않지만, 일반적으로 'aggregation' 작업에는 성능에 유의 하면서 사용을 하는 편인 것 같다.

아래와 같이 설정한다.

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "my_text_field": {
          "type": "text"
        }
      }
    }
  }
}

하지만, 문자열을 색인하는 'text' 타입 필드에 대해서,
때로는 sorting이나 aggregation에 성능이슈 없이 사용 (keyword 타입처럼) 해야할 경우가 생길 것이다. 이 경우엔 해당 필드를 text 타입으로 설정 하면서 동시에 keyword 타입의 용도로도 사용할 수 있는 방법이 있는데, 아래와 같다.

PUT my_index
{
  "mappings": {
    "my_type": {
      "properties": {
        "city": {
          "type": "text",
          "fields": {
            "raw": {
              "type":  "keyword"
            }
          }
        }
      }
    }
  }
}

위와 같이 'city' 라는 필드에 타입은 'text'로 설정 했지만, 해당 설정 하위에 'fields' 속성을 추가하여 그 하위에 'raw' 속성을 "type": "keyword" 로 설정 하였다. 이렇게 되면 필요에 따라 keyword 타입의 용도로 해당 필드를 사용 할 수 있게 된다.

예를 들어 아래와 같은 문자열이 색인 되었다고 했을 때,

PUT my_index/my_type/1
{
  "city": "New York"
}

아래에서 보는 것과 같이 query 작업엔 text 타입의 용도 ('york' 단어 하나로만 질의) 로 검색하고, sort 작업엔 keyword 타입의 용도로 사용 할 수 있다.

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