엘라스틱은 외국에서 만들어졌기 때문에 영어기반의 형태소 분석기가 기본입니다.
한국어에는 다양한 품사와 활용어 등이 있기 때문에 그에 맞는 형태소 분석기가 필요합니다.
여러가지가 있지만 엘라스틱에서 정식적으로 채용한 형태소 분석기는 노리형태소 분석기입니다.
설치 방법은 엘라스틱 메뉴얼을 참조하시길 바랍니다.
https://esbook.kimjmin.net/06-text-analysis/6.7-stemming/6.7.2-nori
📝노리형태소 분석기 생성
PUT my_nori
{
"settings": {
"analysis": {
"tokenizer": {
"nori_none": {
"type": "nori_tokenizer",
"decompound_mode": "none"
},
"nori_discard": {
"type": "nori_tokenizer",
"decompound_mode": "discard"
},
"nori_mixed": {
"type": "nori_tokenizer",
"decompound_mode": "mixed"
}
}
}
}
}
노리형태소 분석기에는 다양한 분해 단계가 있습니다.
- none
- 합성어만 저장합니다
- discard
- 합성어를 분리해 각 어근(의미있는 단어)만 저장합니다
- mixed
- 어근과 합성어 모두 저장합니다. (none + mixed)
📝노리형태소 분석기 테스트 (형태소 분석기) [ none ]
# none
GET my_nori/_analyze
{
"tokenizer": "nori_none",
"text": [ "백두산이" ]
}
# --- result ---
{
"tokens" : [
{
"token" : "백두산",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0
},
{
"token" : "이",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 1
}
]
}
📝노리형태소 분석기 테스트 (형태소 분석기) [ discard ]
# discard
GET my_nori/_analyze
{
"tokenizer": "nori_discard",
"text": [ "백두산이" ]
}
# --- result ---
{
"tokens" : [
{
"token" : "백두",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "산",
"start_offset" : 2,
"end_offset" : 3,
"type" : "word",
"position" : 1
},
{
"token" : "이",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 2
}
]
}
📝노리형태소 분석기 테스트 (형태소 분석기) [ mixed ]
# mixed
GET my_nori/_analyze
{
"tokenizer": "nori_mixed",
"text": [ "백두산이" ]
}
# --- result ---
{
"tokens" : [
{
"token" : "백두산",
"start_offset" : 0,
"end_offset" : 3,
"type" : "word",
"position" : 0,
"positionLength" : 2
},
{
"token" : "백두",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0
},
{
"token" : "산",
"start_offset" : 2,
"end_offset" : 3,
"type" : "word",
"position" : 1
},
{
"token" : "이",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 2
}
]
}
- 이러한 기준으로 품사 분해되어 저장됩니다 이걸 이용해 필요 없는 품사를 없앨 수 있습니다
- 예를 들어 IC 감탄사 "아!" 이런 부분은 검색에 의미가 없죠
📝불용어 (stopwords)
PUT my_pos
{
"settings": {
"index": {
"analysis": {
"filter": {
"my_pos_f": {
"type": "nori_part_of_speech",
"stoptags": [
"NR"
]
}
}
}
}
}
}
이런식으로 필터를 추가해 분석기 튜닝이 가능합니다.
📝상세 형태소 분석
GET _analyze
{
"tokenizer": "nori_tokenizer",
"text": "동해물과 백두산이",
"explain": true
}
# --- result ---
{
"detail" : {
"custom_analyzer" : true,
"charfilters" : [ ],
"tokenizer" : {
"name" : "nori_tokenizer",
"tokens" : [
{
"token" : "동해",
"start_offset" : 0,
"end_offset" : 2,
"type" : "word",
"position" : 0,
"bytes" : "[eb 8f 99 ed 95 b4]",
"leftPOS" : "NNP(Proper Noun)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "NNP(Proper Noun)",
"termFrequency" : 1
},
{
"token" : "물",
"start_offset" : 2,
"end_offset" : 3,
"type" : "word",
"position" : 1,
"bytes" : "[eb ac bc]",
"leftPOS" : "NNG(General Noun)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "NNG(General Noun)",
"termFrequency" : 1
},
{
"token" : "과",
"start_offset" : 3,
"end_offset" : 4,
"type" : "word",
"position" : 2,
"bytes" : "[ea b3 bc]",
"leftPOS" : "J(Ending Particle)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "J(Ending Particle)",
"termFrequency" : 1
},
{
"token" : "백두",
"start_offset" : 5,
"end_offset" : 7,
"type" : "word",
"position" : 3,
"bytes" : "[eb b0 b1 eb 91 90]",
"leftPOS" : "NNG(General Noun)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "NNG(General Noun)",
"termFrequency" : 1
},
{
"token" : "산",
"start_offset" : 7,
"end_offset" : 8,
"type" : "word",
"position" : 4,
"bytes" : "[ec 82 b0]",
"leftPOS" : "NNG(General Noun)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "NNG(General Noun)",
"termFrequency" : 1
},
{
"token" : "이",
"start_offset" : 8,
"end_offset" : 9,
"type" : "word",
"position" : 5,
"bytes" : "[ec 9d b4]",
"leftPOS" : "J(Ending Particle)",
"morphemes" : null,
"posType" : "MORPHEME",
"positionLength" : 1,
"reading" : null,
"rightPOS" : "J(Ending Particle)",
"termFrequency" : 1
}
]
},
"tokenfilters" : [ ]
}
}
형태소 분석기는 검색에 지대한 영향을 끼치기 때문에 어떤식으로 분해되고 어떤 품사인지에 대해서 알려주는 옵션도 있습니다.
📝사용자 사전 (user_dictionary)
PUT my_nori
{
"settings": {
"analysis": {
"tokenizer": {
"my_nori_tokenizer": {
"type": "nori_tokenizer",
"user_dictionary" : "dictionary/newly_coined_word/newly_coined_word_sungjaefileinc.txt"
}
}
}
}
}
노리 형태소 분석기가 원하는대로 분석이 안 되는 경우 사용자 사전을 추가하여 원하는 방향으로 유도할 수 있습니다.
배열로 하나씩 넣어줄 수 있지만 관리하기도 어려워지고 지저분해지기 때문에 텍스트 파일 즉 사용자 사전을 따로 만들어 관리해주는게 좋습니다.
${엘라스틱 설치 위치}/config/ 가 기본 root directory 입니다.
📝불용어 사전 (stopwords)
{
"settings":{
"analysis":{
"filter":{
"my_stop_filter":{
"type":"stop",
"stopwords_path":"dictionary/stopword/stopword_menu.txt"
}
},
"analyzer":{
"nori_analyzer":{
"filter":[
"my_stop_filter"
],
"tokenizer":"korean_nori_tokenizer"
}
},
"tokenizer":{
"korean_nori_tokenizer":{
"type":"nori_tokenizer",
"user_dictionary":"dictionary/newly_coined_word/newly_coined_word_menu.txt",
"decompound_mode":"none"
}
}
}
}
}
📝동의어 사전 (synonym)
{
"settings":{
"analysis":{
"filter":{
"my_synonym":{
"type":"synonym_graph",
"synonyms_path":"dictionary/synonym/synonym_menu.txt",
"lenient":"true"
}
},
"analyzer":{
"nori_analyzer":{
"filter":[
"my_synonym"
],
"tokenizer":"korean_nori_tokenizer"
}
},
"tokenizer":{
"korean_nori_tokenizer":{
"type":"nori_tokenizer",
"user_dictionary":"dictionary/newly_coined_word/newly_coined_word_menu.txt",
"decompound_mode":"none"
}
}
}
}
}
type이 synonym_graph인 경우 인덱스를 close 및 open시 즉시 적용이 된다.
📝open, close
POST my_nori/_close
POST my_nori/_open
인덱스를 닫을 경우 검색이 안되며 오픈을 해야 검색이 가능하다. (close 후 open시 사용자 사전[신조어] 및 동의어가 바로 적용이 된다)
'[ELK]' 카테고리의 다른 글
[ELK] 검색엔진에 사용한 API 모음 (Docker Fargate 설정) (0) | 2023.04.30 |
---|---|
[ELK] 엘라스틱(Elastic) 인덱스 CRUD [노리분석기 Nori] (0) | 2022.09.12 |