본문 바로가기

데이터베이스/ELK

[ELK] Elasticsearch nori 형태소 분석기의 stoptags 한글 품사

0. 문제점

앞의 글에서 버킷 집계에 대하여 정리하였다. 하지만 인덱스를 생성하는 세팅에서 문제점을 발견했다. 

짜잘한건 냅두고 가장 큰 문제점은 한글 형태소 분석기의 품사 태크를 설정하지 않아서 아래처럼 문장이 이상하게 분리되었다.

"aggregations" : {
    "term_aggs" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "ᄇ니다",
          "doc_count" : 1
        },
        {
          "key" : "가",
          "doc_count" : 1
        },
        {
          "key" : "애국",
          "doc_count" : 1
        },
        {
          "key" : "이",
          "doc_count" : 1
        }
      ]
    }
  }

 

 

1. stoptags 품사 태그 종류

값(tag) 영문명 한글명 예시
E Verbal endings 어미 사랑/하(E)/다
IC Interjection 감탄사 와우(IC), 맙소사(IC)
J Ending Particle 조사 나/는(J)/너/에게(J)
MAG General Adverb 일반 부사 빨리(MAG)/달리다, 과연(MAG)/범인/은/누구/인가
MAJ Conjunctive adverb 접속 부사 그런데(MAJ), 그러나(MAJ)
MM (*) ES:Modifier(한정사), 루씬 API:Determiner(관형사) 설명이 다름 맨(MM)/밥
NA Unknown 알 수 없음  
NNB Dependent noun (following nouns) 의존명사  
NNBC Dependent noun 의존명사(단위를 나타내는 명사)  
NNG General Noun 일반 명사 강아지(NNG)
NNP Proper Noun 고유 명사 비숑(NNP)
NP Pronoun 대명사 그것(NP), 이거(NP)
NR Numeral 수사 하나(NR)/밖에, 칠(NR)/더하기/삼(NR)
SC(*) Separator (· / :) 구분자 nori_tokenizer가 특수문자 제거
SE(*) Ellipsis 줄임표(...) nori_tokenizer가 특수문자 제거
SF(*) Terminal punctuation (? ! .) 물음표, 느낌표, 마침표 nori_tokenizer가 특수문자 제거
SH Chinese character 한자 中國(SH)
SL Foreign language 외국어 hello(SL)
SN Number 숫자 1(SN)
SP Space 공백  
SSC(*) Closing brackets 닫는 괄호 ),] nori_tokenizer가 특수문자 제거
SSO(*) Opening brackets 여는 괄호 (,[ nori_tokenizer가 특수문자 제거
SY Other symbol 심벌  
UNA Unknown 알 수 없음  
UNKNOWN Unknown 알 수 없음  
VA Adjective 형용사 하얀(VA)/눈
VCN Negative designator 부정 지정사(서술격조사) 사람/이/아니(VCN)/다
VCP Positive designator 긍정 지정사(서술격조사) 사람/이(VCN)/다
VSV Unknown 알 수 없음  
VV Verb 동사 움직이(VV)/다,먹(VV)/다
VX Auxiliary Verb or Adjective 보조 용언 가지/고/싶(VX)/다, 먹/어/보(VX)/다
XPN(*) Prefix 접두사(체언 접두사?) ES에서 매핑되는 단어를 찾지 못함
XR(*) Root 어근 ES에서 매핑되는 단어를 찾기 못함
XSA Adjective Suffix 형용사 파생 접미사 멋/스럽(XSA)/다
XSN(*) Noun Suffix 명사 파생 접미사 ES에서 매핑되는 단어를 찾기 못함
XSV(*) Verb Suffix 동사 파생 접미사 ES에서 매핑되는 단어를 찾기 못함

뭐 이렇게 많지만... 실질적으로 우리는 

"E", "IC", "J", "MAG", "MAJ", "MM", "SP", "SSC", "SSO", "SC", "SE", "XPN", "XSA", "XSN", "XSV", "UNA", "NA", "VSV"

위에 코드를 그냥 복붙하면 된다. 물론 이것만으로는 현재 우리가 사용하고 있는 신조어까지 분리시킬 수 없다.

신조어까지 감당하게 만드려면 한글 사전을 추가로 만들어서 인덱스에 설정해야한다.

 

 

2. 품사 태그가 적용된 인덱스 생성

이제 품사 태그를 인덱스에 설정한다.

PUT elk-test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "nori_analyzer": {
          "type": "custom",
          "tokenizer": "nori_tokenizer",
          "filter": "nori_filter"
        }
      },
      "tokenizer": {
        "nori_tokenizer": {
          "type": "nori_tokenizer",
          "decompound_mode": "none"
        }
      }, 
      "filter": {
        "nori_filter": {
          "type": "nori_part_of_speech",
          "stoptags": [
              "E", "IC", "J", "MAG", "MAJ", "MM", "SP", "SSC", "SSO", "SC", "SE", "XPN", "XSA", "XSN", "XSV", "UNA", "NA", "VSV"
            ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message.title": {
        "type": "text",
        "analyzer": "nori_analyzer",
        "fielddata": true
      },
      "message.content": {
        "type": "text",
        "analyzer": "nori_analyzer",
        "fielddata": true
      }
    }
  }
}

이전 글의 코드와 꽤 다를 것이다. 실수가 많아서 고치느라 ㅎㅎ;;;

analyzer와 tokenizer, filter 설정을 꼭 해야한다. nori_filter 이런 코드는 filter 설정을 하기 위한 이름에 불과하다. 다른걸로 바꿔도 됨 ㅇㅇ

 

위처럼 인덱스를 생성하고, 도큐먼트를 새로 생성한 다음 버킷 집계를 해보면 아래와 같이 이전보다 더 깔끔하게 데이터가 반환된다.

"aggregations" : {
    "term_aggs" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "동해",
          "doc_count" : 1
        },
        {
          "key" : "물",
          "doc_count" : 1
        },
        {
          "key" : "백두산",
          "doc_count" : 1
        },
        {
          "key" : "어쩔",
          "doc_count" : 1
        },
        {
          "key" : "티비",
          "doc_count" : 1
        }
      ]
    }
  }