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

6. 데이터 색인과 텍스트 분석

by N.Damgom 2021. 9. 6.

6. 데이터 색인과 텍스트 분석

  • 풀텍스트 검색을 위해서는 원본 데이터를 검색에 맞게 가공해야 한다.
  • 엘라스틱서치는 데이터를 저장하면서 데이터를 가공한다.

6.1 역인덱스

  • Full text 검색을 할 때는 역인덱스 구조가 유리하다.
  • key는 term으로, value는 해당 term을 저장하고 있는 문서 번호를 저장한다.
  • 역인덱스는 데이터가 저장될 때 만들어진다. 따라서 엘라스틱서치에서 데이터를 저장하는 과정을 인덱싱(색인)이라고 한다.

6.2 텍스트 분석

  • 텍스트 분석: 원본 데이터로부터 검색어 토큰을 만들어서 저장하는 과정이다.
  • 텍스트 분석 결과는 검색에만 사용되지, 원본 데이터는 변경되지 않는다.
  • 애널라이저: 텍스트 분석을 담당하는 모듈이다.
    • 캐릭터 필터: 전체 문장에서 특정 문자를 제거한다. 애널라이저는 0~3개의 캐릭터 필터로 이루어진다.
    • 토크나이저: 문장에 속한 단어들을 텀 단위로 분리한다. 반드시 애널라이저 당 1개만 적용 가능하다.
    • 토큰 필터: 분리된 텀들을 가공한다. 0~n개 지정할 수 있으며 순서가 의미 있다.(lowercase, stopword, snowball, synonym 등)

6.3 애널라이저

6.3.1 Analyze API

  • GET _analyze API로 분석된 문장을 확인할 수 있다.
GET _analyze
{
  "text": "The quick brown fox jumps over the lazy dog",
  "tokenizer": "whitespace",
  "filter": [
    "lowercase",
    "stop",
    "snowball"
  ]
}

 

  • 애널라이저는 필터와 토크나이저를 조합해서 만들 수도 있고, 기본 제공 애널라이저를 사용할 수도 있다.
  • snowball 애널라이저: whitespace + lowercase, stop, snowball
  • 애널라이저를 필드에 매핑하는 방법은 다음과 같다.
PUT my_index2
{
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "analyzer": "snowball"
      }
    }
  }
}

 

  • 토큰 필터는 순서가 중요하다.
  • 검색 시에도 검색어도 analyzer를 거친다.
  • 이 외 사용 가능한 애널라이저, 필터는 공식 도큐먼트를 확인하자.

6.3.2 Term 쿼리

  • term 쿼리는 애널라이저 적용 없이 입력한 검색어 그대로 검색한다.
GET my_index2/_search
{
  "query": {
    "term": {
      "message": "jump"
    }
  }
}

 

  • 원본 데이터 jumps 는 jump로 저장되므로 term 쿼리 검색어로 jump를 사용해야한다.

6.3.3 사용자 정의 애널라이저

  • 캐릭터 필터, 토크나이저, 토큰 필터를 조합해서 사용자 정의 애널라이저를 만들 수 있다.
  • 인덱스의 setting-index-analysis-analyzer 안에 정의한다.
  • 사용자 정의 토큰 필터
    • settings-index-analysis-filter에서 지정한다.
PUT my_index3
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_custom_analyzer": {
            "type": "custom",
            "tokenizer": "whitespace",
            "filter": [
              "lowercase",
              "my_stop_filter", ## 커스텀 필터
              "snowball"
            ]
          }
        },
        "filter": {
          "my_stop_filter": { ## 커스텀 필터는 analysis-filter에 정의한다.
            "type": "stop",
            "stopwords": [
              "brown"
            ]
          }
        }
      }
    }
  }
}

 

  • text 필드마다 애널라이저를 따로 지정할 수 있다.
PUT my_index3
{
  "settings": {
    "index": {
      "analysis": {
        "analyzer": {
          "my_custom_analyzer": {
            "type": "custom", ## custom한 analyzer
            "tokenizer": "whitespace",
            "filter": [
              "lowercase",
              "my_stop_filter", ## 사용자 정의 필터를 지정한다.
              "snowball"
            ]
          }
        },
        "filter": {
          "my_stop_filter": { ## 사용자 정의 필터
            "type": "stop",
            "stopwords": [
              "brown"
            ]
          }
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": { ## message라는 필드에
        "type": "text",
        "analyzer": "my_custom_analyzer" ## 어떤 analyzer를 사용할지.
      }
    }
  }
}

 

6.3.4 텀 벡터

  • 역인덱스 내용을 확일할 때는 _termbvectors API를 활용하면 된다.
GET <인덱스명>/_termvectors/<id>?fields=<필드명>,...

6.4 캐릭터 필터

  • 토크나이징 되기 전 전체 문장에 대한 전처리 과정이다.
  • 세 종류가 존재한다.
  • HTML Strip: Html 문법 용어를 해석하고, 태그들을 제거한다.
  • Mapping: 특수문자는 토크나이저나 토큰 필터에 의해 제거되므로 다른 문자로 치환한다.
  • PUT coding
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "coding_analyzer": {
              "char_filter": [
                "cpp_char_filter" ## cpp_char_filter라는 커스텀 캐릭터 필터를 적용한다.
              ],
              "tokenizer": "whitespace",
              "filter": [ "lowercase", "stop", "snowball" ] ## snowball 애널라이저 설정
            }
          },
          "char_filter": { # custom char_filter를 적용한다.
            "cpp_char_filter": {
              "type": "mapping", # type은 매핑
              "mappings": [ "+ => _plus_", "- => _minus_" ] # 매핑정보
            }
          }
        }
      },
      "mappings": {
        "properties": {
          "language": {
            "type": "text",
            "analyzer": "coding_analyzer" ## language 필드에 커스텀 애널라이저를 적용한다.
          }
        }
      }
    }
  • Pattern Replace: 정규식 패턴을 이용해서 치환한다.
  • PUT camel
    {
      "settings": {
        "analysis": {
          "analyzer": {
            "camel_analyzer": {
              "char_filter": [
                "camel_filter"
              ],
              "tokenizer": "standard",
              "filter": [
                "lowercase"
              ]
            }
          },
          "char_filter": {
            "camel_filter": {
              "type": "pattern_replace", ## pattern_replace 타입
              "pattern": "(?<=\\p{Lower})(?=\\p{Upper})",
              "replacement": " "
            }
          }
        }
      }
    }

6.5 토크나이저

  • 애널라이저는 반드시 한개만 사용하며, tokenizer 항목에 단일값으로 설정한다.
  • 여러 종류가 있으며 공식 도큐먼트를 참조하자.
  • standard: 공백으로 텀을 구분하면서 따로 떨어져 있거나 끝에 있는 특수문자를 제거한다.
  • letter: 알파벳을 제외한 모든 공백, 숫자, 기호들을 기준으로 텀을 분리한다.
  • whitespace: 스페이스, 탭, 줄바꿈 같은 공백만을 기준으로 텀을 분리한다.
  • 보통 standard를 많이 쓴다.
  • uax_url_email: 이메일 주소, 웹 url 경로는 분리하지 않는다.
  • pattern: IoT, 머신 데이터인 경우 다른 구분자를 쓰므로 pattern으로 구분한다. 특정 문자나 정규식을 사용할 수 있다.
  • PUT pat_tokenizer
    {
      "settings": {
        "analysis": {
          "tokenizer": {
            "my_pat_tokenizer": {
              "type": "pattern",
              "pattern": "/" ## "pattern": "(?<=\\p{Lower})(?=\\p{Upper})"
            }
          }
        }
      }
    }
  • path_hierarchy: 경로를 단계별로 쪼갠다.
    • /A/B/C -> /A, /A/B,/A/B/C
    • delimiter와 replacement를 지정할 수 있다.

6.6 토큰 필터

  • analysis 밑의 filter 항목에 배열로 나열해서 정한다.
  • 필터를 설정하는 순서에 유의하자.
  • lowercase, uppercase: 거의 모든 곳에서 사용된다.
  • stopword
    • 불용어를 배열 형태로 지정하거나 _english_와 같이 언어팩을 사용할 수 있다.
    • 불용어를 사용하기 위해선 사전에 lowercase 필터가 필요하다.
    • stopwords_path로 텍스트 파일을 지정해줄 수 있다.
    • PUT my_stop
      {
        "settings": {
          "analysis": {
            "filter": {
              "my_stop_filter": { ## 필터 정의 부분
                "type": "stop",
                "stopwords_path": "user_dic/my_stop_dic.txt"
              }
            }
          }
        }
      }
  • synonym
    • 동의어 필터이다.
    • "A,B => C" : A,B 대신 C를 저장한다. A,B로 C를 검색 가능하나 C로 A,B를 검색할 수는 없다.
    • "A, B" => A와 B 각 텀이 A, B 두 개의 텀을 저장한다.
    • 마찬가지로 "synonyms_path"로 파일을 지정할 수 있다.
    • PUT my_synonym
      {
        "settings": {
          "analysis": {
            "analyzer": {
              "my_syn": {
                "tokenizer": "whitespace",
                "filter": [ ## 토큰 필터를 배열로 지정
                  "lowercase",
                  "syn_aws"
                ]
              }
            },
            "filter": {
              "syn_aws": { ## 필터 정의 부분
                "type": "synonym",
                "synonyms_path": "user_dic/my_syn_dic.txt"
              }
            }
          }
        },
        "mappings": {
          "properties": {
            "message": {
              "type": "text",
              "analyzer": "my_syn"
            }
          }
        }
      }
    • expand 옵션: default는 true, false 시 동의어를 둘다 저장하지 않고 앞의 하나만 저장한다.
    • lenient 옵션: default는 false, true 시 synonym의 오류를 무시한다.
  • Ngram
    • 부분 문자열을 저장한다.
      • ex) bigram : house: ho,ou,us,se
    • 전체 개수가 많지 않은 데이터 집단에 자동 완성으로 쓴다.
    • min_gram, max_gram을 지정할 수 있다.
    • Edge NGram: 맨 앞부터 쌓아가며 부분 문자열을 만든다.
    • Shingle: 단어 단위로 묶는다.
    • Ngram, Shingle은 일반적으로 사용되지 않으나 자동완성, 문법 검색 등 특수한 환경에서 사용된다.
  • unique: 중복되는 term을 하나만 저장한다. 스코어에 영향을 주므로 match를 쓸 때는 쓰지 말자.

6.7 형태소 분석

  • 형태소 분석: 어간을 추출하는 과정
  • snowball: ~ing, ~s 등을 제거한다. 애널라이저, 토크나이저, 토큰필터 모두 정의되어 있다.
  • nori: 한글 형태소 분석기
    • nori 플러그인 설치가 필요하다.
    • nori_tokenizer : 토크나이저
      • user_dictionary, user_dictionary_rules: 사용자 정의 사전을 입력한다.
      • decompound_mode: 합성어의 저장 방식을 지정한다.
        • none: 완성된 합성어만 저장한다.
        • discard(default): 어근만 저장한다.
        • mixed: 어근과 합성어 모두 저장한다.
    • nori_part_of_speech : 토큰 필터
      • 제거할 품사를 지정한다.
      • stoptags 값에 배열로 저장한다.
      • 보통 명사, 동명사 정도만 검색한다.
    • nori_reading_from: 토큰 필터
      • 한자를 한글로 바꾼다.
    • _analyze API 에서 "explain": true로 형태소의 동사 정보를 볼 수 있다.

'엘라스틱서치' 카테고리의 다른 글

레퍼런스] 엘라스틱서치란 무엇인가?  (0) 2021.09.15
7. 인덱스 설정과 매핑  (0) 2021.09.06
5. 검색과 쿼리  (0) 2021.09.05
4. 데이터 처리  (0) 2021.08.31
3. 시스템 구조  (0) 2021.08.31