본문 바로가기
TIL/엘라스틱 서치

Elastic Search : Complete Guide to ElasticSearch - 매핑과 분석기에 대한 추천

by yeon_zoo 2024. 2. 4.


[매핑에 대한 추천]

  • 명시적 매핑을 사용해라
    • 다이나믹 매핑이 편하긴 하지만 프로덕션에서 좋은 아이디어는 아니다.
    • 많은 문서를 저장할 때는 최적화된 매핑이 저장소를 아낄 수 있다.
    • dynamic을 false 가 아니라 strict 로 두라는 뜻
    • 깜짝 놀랄만하거나 기대하지 못한 결과를 마주할 일이 없다.
  • 항상 text이자 keyword로 멀티 매핑하는 것을 피해라
    • 보통은 둘 중에 하나만 필요하다.
    • 각 매핑은 디스크 공간을 필요로 한다.
    • 전문 검색이 필요 > 텍스트
    • 집계, 정렬, 필터링이 필요 > 키워드
  • coercion (강제 형변환)을 비활성화해라
    • 강제 형변환은 올바르지 않은 행동도 용인하게 된다.
    • 가능하면 항상 올바른 데이터 형을 사용해라.
  • 적절한 숫자 데이터 형을 사용해라
    • int형이 충분한 경우가 많다.
      • long은 더 큰 숫자를 저장할 수 있지만 동시에 저장공간도 더 많이 쓴다.
    • 소수는 float 타입으로 충분할 수 있다.
      • double은 float 보다 더 정확성을 가지지만 2배의 저장공간을 쓴다. 보통은 float 타입으로도 충분한 정확성을 제공한다.
  • 매핑 파라미터
    • doc_values : false => 정렬, 집계, 스크립팅이 필요없는 경우
    • norms: false => 관계도 점수가 필요 없는 경우
    • index: false => 값에 필터링할 필요 없는 경우
    • 집계는 여전히 가능 (e.g. 시계열 데이터)
  • 문서 수가 많으면 가치가 있지만 문서수가 적은 경우는,, 오히려 이런 설정을 하기 위한 복잡도가 더 높을 것
    • 명확한 숫자는 없지만, 보통 백만개 이상이라면 이런 설정을 하는 것이 좋다.
  • 만약 초기에 하지 않았다면.. 그냥 리인덱싱 하면 된다. (세상의 종말은 아니다!)

 

 

[Text Analysis - 형태소 분석 (Stemming) & 불용어 (Stop words)]

  • 형태소 분석
    • 시제나 복수형 등등을 제거하여 어근만 남김
  • 불용어
    • 텍스트 분석 중에 필터링되는 단어들 e.g. “a”, “the”, “at”, “of”, etc
    • 관계도 점수에 거의 영향을 미치지 않아야 한다.
    • 이런 단어들은 제거하는 것이 흔하다.
      • 현재에 와서는 과거보단 덜 흔하다. 관계도 계산 알고리즘이 많이 발전했기 때문
    • 기본값으로 제거되는 것은 아니고, 그렇게 하기를 추천하지도 않는다.
  • 서치 쿼리를 날릴 때
    • 검색어 자체도 형태소 분석 + 불용어를 제거하고 남은 단어로 검색한다.
      • e.g.) drinking을 검색 -> drink 만 포함된 것도 검색 결과로 나옴.

 

[내장 분석기]

  • 스탠다드 분석기
    • 단어마다 나누고 문장 부호들을 제거한다. (by, standard tokenizer)
    • lowercase 토큰 필터에 의해 문자들을 소문자화 한다.
    • stop 토큰 필터를 가지고 있지만 기본값으로 비활성화되어 있다.
  • 심플 분석기
    • 스탠다드 분석기랑 유사
      • 문자 외에 다른 것들은 전부 토큰으로 쪼갠다 (스탠다드는 단어마다 쪼갬)
    • 소문자로 변환 (lowercase 토큰 필터가 아니라 lowercase 토크나이저에 의해)
      • 흔한 일은 아니지만 입력값을 두 번 훑는 성능 함정(?)을 피하기 위해서 발생
    • whitespace 분석기
      • 공백을 기준으로 토큰으로 나누고, 소문자화 하지 않음
    • 키워드 분석기
      • 입력된 텍스트를 그대로 놔두는 no-op 분석기이다. 입력값 그대로를 하나의 토큰으로 출력값을 만든다.
      • 기본값으로 키워드 필드에 사용한다.
      • 정확히 매칭되는 값을 위해 사용
  • 패턴 분석기
    • 정규 표현식으로 토큰 분할 기준을 잡는다.
    • 유연성이 높다
    • 기본값은 단어가 아닌 모든 문자들을 기준으로 나눈다. (\W+)
    • 소문자화는 기본 (비활성화 가능)
    • 그 외 각 언어 별 분석기가 존재. (language analyzer)
  • english analyzer 적용 예시
PUT /products 
{
  "mappings": {
    "properties": {
      "description": {
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}
  • 스탠다드 분석기의 확장판으로 사용
PUT /products
{
  "settings": {
    "analysis": {
      "analyzer": {
        "remove_english_stop_words": {
          "type": "standard",
          "stopwords": "_english_"
        }
      }
    }
  }
}

 

[분석기 커스텀]

언어별 분석기로 커스텀

PUT /analyzer_test
{
	"settings": {
		"analysis": {
			"filter": {
				"danish_stop": {
					"type": "stop",
					"stopwords": "_danish_" // 불용어들을 영어 대신 덴마크어로 사용하도록 함
				}
			},
			"analyzer": {
				"my_custom_analyzer": {
					"type": "custom",
					"char_filter": ["html_strip"],
					"tokenizer": "standard",
					"filter": [
						"lowercase",
						"danish_stop",
						"asciifolding"
					]
				}
			}
		}
	}
}
  • 분석기 (그 중에서도 토큰 필터)는 정말 많은 종류가 있으므로(e.g. 동의어.. 등) 실제 커스텀 분석기를 쓰게 된다면 여기서 확인해서 잘 써라..

 

[이미 있는 인덱스에 분석기 추가하기]

  • 오픈 인덱스는 인덱싱과 서치 요청이 가능한 인덱스를 의미하고, closed 인덱스는 그 반대를 의미한다.
    • closed : 읽기와 쓰기 요청이 막혀 있다.
  • 인덱스 설정의 두 가지 : dynamic & static
    • 다이나믹 설정은 인덱스를 닫지 않고도 바꿀 수 있다. : 다운 타임 없음
    • 스태틱 설정은 인덱스가 먼저 닫혀있어야 한다. : 다운 타임 존재
  • 분석기 설정은 스태틱 설정이다
    • 따라서 먼저 인덱스를 닫고, 변경을 해줘야 한다.
  • 인덱스를 닫는 법
    • POST /analyzer_test/_close
  • 인덱스 분석기 수정 요청
PUT /analyzer_test/_settings
{
	"analysis": {
		"analyzer": {
			"my_second_analyzer": {
				"type": "custom",
				"tokenizer": "standard",
				"char_filter": ["html_strip"],
				"filter": [
					"lowercase",
					"stop",
					"acsiifolding"
				]
			}
		}
	}
}
  • 인덱스 여는 법
    • POST /analyzer_test/_open
  • 인덱스를 열고 닫는 건 빠르긴 하지만 프로덕션 클러스터에서는 고려할만한 옵션이 아닐 수도 있다.
    • 대체안으로, 도큐먼트들을 리인덱싱할 수도 있다.
    • 업데이트된 세팅으로 새로운 인덱스를 만든다.
    • 변환에는 인덱스 alias 를 사용한다.

 

[기존 분석기 수정]

  • 별도로 쿼리에 분석기를 지정해주지 않으면, 해당 필드에 사용된 분석기로 쿼리를 분석한다.
    • 따라서 필드에 stop 필터를 걸고, “that”으로 검색하게 되면, 실제로 검색되는 쿼리는 없다.
  • 아래처럼 keyword analyzer로 쿼리하면 that이 사라지지 않고 정상적으로 질의가 가능하다.
    • 불용어를 검색해야 될 때는 아래와 같이 쓸 수 있다.
GET /analyzer_test/_search
{
	"query": {
		"match": {
			"description": {
				"query": "that",
				"analyzer": "keyword"
			}
		}
	}
}
  • 분석기 업데이트 예시 (인덱스를 먼저 닫고 실행해야함)
GET /analyzer_test/_search
{
	"query": {
		"match": {
			"description": {
				"query": "that",
				"analyzer": "keyword"
			}
		}
	}
}
  • 업데이트 전 분석기로 분석된 도큐먼트들은 자동 재분석 되는 것이 아니라 이전 분석 결과대로 남아있다.
    • 리인덱싱 할 수도 있긴 함.
    • update_by_query로 해결 가능
      • POST analyzer_test/_update_by_query?conflicts=proceed

 

댓글