본문 바로가기
DataOps/Elasticsearch

[Elasticsearch] 3. 인덱스 설계 (Analyzer, Tokenizer)

by BenKangKang 2024. 3. 13.

TL;DR

- 애널라이저: 문장이 들어오면 변형, 필터링을 거쳐 의도한 Term 단위로 저장할 때 사용함

- 캐릭터 필터: HTML 와 같은 포맷에서 필요한 문장만 뽑아냄

- 토크나이저: 문장을 원하는 방식으로 쪼갬

- 토큰 필터: 불용어, 공백 등 토크나이징된 결과물 중 필요없는 단어 제거

- 애널라이저는 캐릭터 필터, 토크나이저, 토큰 필터로 구성된다.

- 노말라이저는 키워드 타입에 적용 가능하므로, 토크나이저가 없다. (키워드는 토크나이징을 거치지 않는다)

 

3.3 애널라이저와 토크나이저

의미

  • 들어온 문자열에 변형을 가해 분석 완료된 “텀”을 얻는다.

구성

  • 캐릭터 필터
    • 0개 이상
    • 문자열 변형
  • 토크나이저
    • 1개
    • 토큰 쪼개기
  • 토큰 필터
    • 0개 이상
    • 토큰 변형

3.3.1 analyze API

  • 애널라이저와 각 구성 요소 동작을 쉽게 테스트할 수 있는 API
POST /_analyze
{
    "analyzer": "standard",
    "text": "Hello, HELLO, World!"
}

3.3.2 캐릭터 필터 (Character filter)

  • 텍스트를 캐릭터의 스트림으로 받아서 특정한 문자를 추가,. 변경, 삭제
  • 0개 이상의 캐릭터 필터 지정 가능
  • 캐릭터 필터가 여러개면 순서대로 수행
  • 빌트인 캐릭터 필터
    • HTMP strip 캐릭터 필터
      • HTML: 요소 안쪽의 데이터를 꺼낸다
    • mapping 캐릭터 필터: 치환할 대상이 되는 문자와 치환 문자를 맵 형태로 선언
    • pattern replace 캐릭터 필터: 정규 표현식을 이용해서 문자를 치환한다.
POST /_analyze
{
    "char_filter": ["html_strip"],
    "text": "<p>Hello, HELLO, World!</p>"
}

3.3.3 토크나이저(Tokenizer)

Standard

  • Unicode Text Segmentation 알고리즘 사용해 텍스트를 단어 단위로 나눈다.
  • 대부분 문장 부호(punctuation symbol)가 사라진다.
  • 애널라이저 지정하지 않으면 기본으로 standard 애널라이저 적용, SA가 바로 이 토크나이저 사용

Keyword

  • 들어온 텍스트 쪼개지 않고 그대로 내보낸다. 즉 커다란 단일 토큰을 내보낸다.

ngram 토크나이저

  • 텍스트를 min_gram 값 이상, max_gram 값 이하 단위로 쪼갠다
    • token_chars 속성
      • 토큰에 포함시킬 문자 지정 가능 (공백 제거 필요한 경우 등)
  • 예시
    • min: 2
    • max: 3
    • input: hello
    • out
      • he, hel, el, ell, ll, llo 총 5개
  • 특징
    • min 보다 적은 글자는 토크나이징 되지 않는다.

ngram 의 token_chars 속성으로 지정할 수 있는 값

 

 

edge_ngram 토크나이저

  • ngram 과 유사한 동작 수행하지만 차이가 있음
    • edge_ngram 토크나이저는 텍스트의 "edge"에서 시작하여 n 글자 길이의 토큰을 생성
    • 여기서 "edge"는 보통 문자열의 시작을 의미합니다. 이 토크나이저는 **min**과 max 길이 사이의 토큰을 생성하지만, 오직 단어의 시작 부분에서만 토큰을 생성합니다.
  • **edge_ngram**은 특히 자동 완성이나 검색어 제안과 같은 기능에 유용합니다. 사용자가 단어의 시작 부분을 타이핑하기 시작할 때 관련 검색 결과를 빠르게 반환할 수 있습니다.

그외

  • letter 토크나이저: 공백, 특수문자 등 언어의 글자로 분류되는 문자가 아닌 문자를 만났을 때 쪼갠다
  • whitespace 토크나이저: 공백 문자를 만났을 때 쪼갠다
  • pattern 토크나이저: 지정한 정규표현식을 단어의 구분자로 사용하여 쪼갠다

3.3.4 토큰 필터

  • 토큰 스트림을 받아서 토큰을 추가, 변경, 삭제한다.
  • 하나의 애널라이저에 토큰 필터 0개 이상 지정 가능
  • 특징
    • 토큰 필터가 여러 개 지정된 경우에는 순차적으로 적용된다.
  • lowercase, uppercase: 토큰의 내용을 소문자/대문자로 만들어 준다
  • stop: 불용어를 지정하여 제거할 수 있다.
  • synonym: 유의어 사전 파일을 지정하여 지정된 유의어를 치환한다
  • pattern_replace: 정규식을 사용하여 토큰의 내용을 치환한다
  • stemmer: 지원되는 몇몇 언어의 어간 추출을 수행한다. 한국어는 지원하지 않는다.
  • trim : 토큰 전후에 위치한 공백 문자를 제거
  • truncate: 지정한 길이로 토큰을 자른다.

3.3.5 내장 애널라이저(Built-in analyzer)

  • 다양한 내장 애널라이저가 있다.
  • standard 애널라이저
    • standard 토크나이저 lowercase 토큰 필터로 구성된다.
    • 특별히 애널라이저를 지정하지 않으면 적용되는 기본 애널라이저
  • simple 애널라이저
    • letter가 아닌 문자 단위로 토큰을 쪼갠 뒤 lowercase 토큰 필터를 적용한다
  • whitespace 애널라이저
    • 공백 단위로 토큰을 쪼갠다
  • stop 애널라이저
    • standard 애널라이저와 같은 내용이지만 뒤에 stop 토큰 필터를 적용해서 불용어를 제거한다
  • keyword 애널라이저
    • keyword 토크나이저로 구성된다
    • 특별히 분석을 실시하지 않고 하나의 큰 토큰을 그대로 반환한다
  • pattern 애널라이저
    • pattern 토크나이저와 lowercase 토큰 필터로 구성된다
  • language 애널라이저
    • 여러 언어의 분석을 지원한다. 한국어 분석을 지원하지 않는다.
  • fingerprint 애널라이저
    • 중복 검출에 사용할 수 있는 특별한 핑거프린트용 토큰을 생성한다
    • 순서
      1. standard 토크나이저 적용
      2. lowercase 토큰 필터 적용
      3. ASCII folding 토큰 필터 적용
        1. 아스키 내에 동격 문자가 있는 경우 치환해준다.
      4. stop 토큰 필터 적용 (기본적으로 비활성화)
      5. fingerprint 토큰 필터 적용

3.3.6 Analyzer를 매핑에 적용

  • index.settings.analysis.analyzer 설정에 커스텀 애널라이저 추가할 수 있다.
    • default 이름으로 애널라이저 지정하면 기본 애너라이저를 변경할 수 있다.
{
    "mappings": {
        "properties": {
            "defaultText": {
                "type": "text"
            },
            "standardText": {
                "type": "text"
								"analyzer": "standard"
            }
        }
    },
    "settings": {
				"analysis": {
					"analyzer": {
						"default": {
							"type": "keyword"
						}
					}
				},
        "number_of_shards": 1,
        "number_of_replicas": 1
    }
}

3.3.7 커스텀 애널라이저

//              "my_stop_filter",
//              "snowball"

GET [인덱스 이름]/_analyze
PUT [인덱스 이름]/_analyze

{
  "settings": {
    "index": {
      "analysis": {
				"char_filter": {
					"my_char_filter": {
						"type": "mapping",
						"mappings": [
							"i. => 1.",
							"ii. => 2.",
							"iii. => 3.",
							"iv. => 4.",
						]
					}
				},
			 "filter": {
          "my_stop_filter": {
            "type": "stop",
            "stopwords": [
              "brown"
            ]
          }
        },
        "analyzer": {
          "my_analyzer": {
						"char_filter": [
							"my_char_filter"
						],
            "tokenizer": "whitespace",
            "filter": [
              "lowercase"
            ]
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "analyzer": "my_analyzer"
      }
    }
  }
}

3.3.8 플러그인 설치해서 애널라이저 추가

  • 한국어 형태소 분석 지원하는 기본 내장 애널라이저는 없음
    • 한국: nori
    • 일본: kuromoji
    • 중국: smartcn

일반 환경

bin/elasticsearch-plugin install analysis-nori

docker-compose

FROM docker.elastic.co/elasticsearch/elasticsearch:8.1.2
RUN elasticsearch-plugin install analysis-nori
{
    "analyzer": "nori",
    "text": "안녕하신가? 정말 반갑구먼, 다음에 또 만나자고~?"
}
{
    "tokens": [
        {
            "token": "안녕",
            "start_offset": 0,
            "end_offset": 2,
            "type": "word",
            "position": 0
        },
        {
            "token": "반갑",
            "start_offset": 10,
            "end_offset": 12,
            "type": "word",
            "position": 5
        },
        {
            "token": "다음",
            "start_offset": 16,
            "end_offset": 18,
            "type": "word",
            "position": 7
        },
        {
            "token": "만나",
            "start_offset": 22,
            "end_offset": 24,
            "type": "word",
            "position": 10
        }
    ]
}

3.3.9 노말라이저

  • 애널라이저와 비슷한 역할을 하나 적용 대상이 text 타입이 아닌 keyword 타입 필드
  • 특징
    • 키워드 타입 필드이기 때문에 단일 토큰을 생성한다.
      • CF, TF만 있고 토크나이저가 없다
      • 마찬가지로 모든 CF, TF를 조할할 수 있는 것이 아니다. 단일 토큰 처리 작업 수행하는 필터만 사용할 수 있다.
        • ASCCI folding, lowercase, uppercase
{
  "settings": {
    "analysis": {
        "nomalizer": {
            "my_normalizer": {
                "type": "custom",
								"char_filter": [],
                "filter": [
									"asciifolding",
									"uppercase"
                ]
            }
        }
      }
  },
  "mappings": {
    "properties": {
      "myNormalizerKeyword": {
        "type": "keyword",
        "normalizer": "my_normalizer"
      },
      "lowercaseKeyword": {
        "type": "keyword",
        "normalizer": "lowercase"
      },
      "defaultKeyword": {
        "type": "keyword"
      }
    }
  }
}

 

댓글