검색엔진 스터디

07장 한글 검색 확장 기능

막이86 2023. 11. 8. 17:30
728x90

엘라스틱서치 실무 가이드 7장을 요약한 내용입니다.

  • Suggest API가 키워드 자동완성 기능을 지원
    • 한글 키워드는 정상 동작하지 않음

7.1 Suggest API 소개

  • Suggest API를 이용하면 텀과 정확히 일치하지 않는 단어도 자동 인식
  • Suggest API 4가지 방식
    • Term Suggest API: 추천 단어 제안
    • Compleetion Suggest API: 자동완성 제안
    • Phrase Suggest API: 추천 문장 제안
    • Context Suggest API: 추천 문맥 제안

7.1.1 Term Suggest API

  • 편집거리(edit distance)를 사용해 비슷한 단어를 제안
  • 문자열이 다른 문자열과 얼마나 비슷한가를 편집거리를 사용해 알아 볼 수 있음
  • 편집거리 측정 방식은 단어를 삽입, 삭제, 치환 연산을 제공
  • 측정 과정은 한 문자열을 다른 문자열로 바꾸는데 필요한 삽입, 삭제, 치환 연산의 수행 횟수
    • “tamming test” → “taming text”
    • m을 1회 삭제, s를 x로 치환 편집거리: 2
  • 테스트 데이터 생성
  • PUT /_bulk { "index" : { "_index" : "movie_term_suggest", "_id" : "1" } } { "movieNm" : "lover" } { "index" : { "_index" : "movie_term_suggest", "_id" : "2" } } { "movieNm" : "Fall love" } { "index" : { "_index" : "movie_term_suggest", "_id" : "3" } } { "movieNm" : "lovely" } { "index" : { "_index" : "movie_term_suggest", "_id" : "4" } } { "movieNm" : "lovestory" }
  • “lave” 검색
    • score는 원본과 얼마나 가까운지 나타낸다
    POST /movie_term_suggest/_search
    {
    	"suggest": {
    		"spell-suggestion": {
    			"text": "lave",
    			"term": {
    				"field": "movieNm"
    			}
    		}
    	}
    }
    
    # 결과
    {
        ...
        "suggest": {
            "spell-suggestion": [
                {
                    "text": "lave",
                    "offset": 0,
                    "length": 4,
                    "options": [
                        {
                            "text": "love",
                            "score": 0.75,
                            "freq": 1
                        },
                        {
                            "text": "lover",
                            "score": 0.5,
                            "freq": 1
                        }
                    ]
                }
            ]
        }
    }
    
    <aside> 💡 한글의 경우에는 Term Suggest를 이용해도 데이터가 추천되지 않음
  • </aside>

7.1.2 Completion Suggest API

  • 자동 완성을 위해 Completion Suggest API를 제공
  • 응답 속도가 매우 중요
  • FST(Finite State Transducer)를 사용
    • 검색어가 메모리로 로드되어 서비스되는 구조
  • 자동완성 기능을 사용하기 위해서는 데이터 타입을 completion으로 설정
  • PUT /movie_term_completion { "mappings": { "_doc": { "properties": { "movieNmEnComple": { "type": "completion" } } } } }
  • 데이터 추가
  • PUT /_bulk { "index" : { "_index" : "movie_term_completion", "_id" : "1" } } { "movieNmEnComple" : "After Love" } { "index" : { "_index" : "movie_term_completion", "_id" : "2" } } { "movieNmEnComple" : "Lover" } { "index" : { "_index" : "movie_term_completion", "_id" : "3" } } { "movieNmEnComple" : "Love for a mother" } { "index" : { "_index" : "movie_term_completion", "_id" : "4" } } { "movieNmEnComple" : "Fall love" } { "index" : { "_index" : "movie_term_completion", "_id" : "5" } } { "movieNmEnComple" : "My lovely wife" }
  • “L”로 시작되는 모든 영화 제목을 검색
    • prefix로 검색할 키워드 설정
    • completion에 검색에 사용할 필드 지정
    • 결과로 5개를 요청
      • 5개를 항상 보장하는 것은 아님
    POST /movie_term_completion/_search
    {
    	"suggest": {
    		"movie_completion": {
    			"prefix": "1",
    			"completion": {
    				"field": "movieNmEnComple",
    				"size": 5
    			}
    		}
    	}
    }
    
  • 자동완성 결과
    • prefix로 제공되는 전방일치 검색 기능에 의해 2개의 문서만 “L”로 시작되는 단어만 검색
    • 반드시 “L”로 시작되어야 함
  • 부분일치를 하고 싶다면 분리해서 배열 형태로 만들어야 한다
  • PUT /_bulk { "index" : { "_index" : "movie_term_completion", "_id" : "1" } } { "movieNmEnComple" : { "input": ["After", "Love"] } } { "index" : { "_index" : "movie_term_completion", "_id" : "2" } } { "movieNmEnComple" : { "input": ["Lover"] } } { "index" : { "_index" : "movie_term_completion", "_id" : "3" } } { "movieNmEnComple" : { "input": ["Love", "for", "a", "mother"] } } { "index" : { "_index" : "movie_term_completion", "_id" : "4" } } { "movieNmEnComple" : { "input": ["Fall", "love"] } } { "index" : { "_index" : "movie_term_completion", "_id" : "5" } } { "movieNmEnComple" : { "input": ["My", "lovely", "wife"] } }
  • 부분일치를 위해 다시 검색
  • POST /movie_term_completion/_search { "suggest": { "movie_completion": { "prefix": "1", "completion": { "field": "movieNmEnComple", "size": 5 } } } }
  • 정상적으로 5건이 출력
  •  

<aside> 💡 Completion Suggest API가 전방일치 방식밖에 지원하지 않아 색인할 때 데이터를 가공해야 함

</aside>

<aside> 💡 한글의 경우 자소를 분해해서 사용하면 자동완성을 만들 수 있다. 플러그인을 통해서 처리 가능 하다

</aside>

7.2 맞춤법 검사기

7.2.1 Term Suggester API를 이용한 오타 교정

  • “삼성전자”를 검색하기 위해 “샴성전자”를 입력한 경우 오타 교정 로직을 만들 수 있다
  • 철자를 교정하기 위해 Suggest API를 제공
    • 한글은 잘 동작 하지 않아 별도의 플러그인 설치

자바카페 플러그인 설치

1) 인덱스 생성

PUT /company_spellchecker
{
	"settings": {
		"index": {
			"analysis": {
				"analyzer": {
					"korean_spell_analyzer": {
						"type": "custom",
						"tokenizer": "standard",
						"filter": [
							"trim",
							"lowercase",
							"javacafe_spell"
						]
					}
				}
			}
		}
	}
}

2) 매핑 설정

PUT /company_spellchecker/_doc/_mappings
{
	"properties": {
		"name": {
			"type": "keyword",
			"copy_to": ["suggest"]
		},
		"suggest": {
			"type": "completion",
			"analyzer": "korean_spell_analyzer"
		}
	}
}

3) 오타 교정 데이터 색인

PUT /company_spellchecker/_doc/1
{
	"name": "삼성전자"
}

4) 오타 교정 API 요청

  • javacafe_spell 필터는 내부적으로 색인된 모든 데이터를 자소 단위로 분해해서 생성
  • 모든 데이터가 자소 단위로 분해됐기 때문에 편집거리 계산이 가능
PUT /company_spellchecker/_doc/_search
{
	"suggest": {
		"my-suggestion": {
			"text": "샴성전자",
			"term": {
				"field": "suggest"
			}
		}
	}
}

## 검색 결과 

7.2.2 한영/영한 오타 교정

  • 한영키 때문에 발생한 오타의 경우 편집거리로 비슷한 단어를 찾는 방식 활용은 불가능
    • “apple” → “메ㅔㅣㄷ”
  • 검색어 자체가 영문으로 유입되어야 하는데 오타 교정 때문에 한글로 변형되어 의도하지 않은 결과가 나오는 경우가 생길 수 있음
    • “DJVNP” 서비스를 검색했지만 “어퓨”로 변형될 수 있음
    • 예제 생성 해보기

1) 인덱스 생성

  • 두 개의 인덱스 생성
  • PUT /company { "settings": { "index": { "analysis": { "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "trim", "lowercase" ] } } } } } } PUT /search_keyword { "settings": { "index": { "analysis": { "analyzer": { "kor2eng_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "trim", "lowercase", "javacafe_spell" ] }, "eng2kor_analyzer": { "type": "custom", "tokenizer": "standard", "filter": [ "trim", "lowercase", "javacafe_spell" ] } } } } } }

2) 매핑 설정

PUT /company/_doc/_mappings
{
	"properties": {
		"name": {
			"type": "keyword"	
		}
	}
}

PUT /search_keyword/_doc/_mappings
{
	"properties": {
		"name": {
			"type": "keyword",
			"copy_to": ["kor2eng_analyzer", "eng2kor_analyzer"]
		},
		"kor2eng_analyzer": {
			"type": "text",
			"analyzer": "standard",
			"search_analyzer": "kor2eng_analyzer"
		},
		"eng2kor_analyzer": {
			"type": "text",
			"analyzer": "standard",
			"search_analyzer": "eng2kor_analyzer"
		}
	}
}

3) 오타 교정 데이터 색인

PUT /company/_doc/1
{ "name": "삼성전자" }

PUT /company/_doc/2
{ "name": "iphone" }

PUT /search_keyword/_doc/1
{ "name": "삼성전자" }

PUT /search_keyword/_doc/2
{ "name": "삼성전자" }

4) 오타 교정 API 요청

  • 오타 교정 API 실행 방법
    1. search_keyword 인덱스에 사용자 검색어를 가지고 검색 질의를 한다.
    2. 검색 결과가 없다면 검색어 그대로 company 인덱스에 검색 질의를 한다.
    3. 검색 결과가 있다면 변경된 검색어로 company 인덱스에 검색 질의를 한다.
  • 한영 오타나 영한 오타가 발생하더라도 실제 데이터를 질의할 때 변경된 검색어로 질의했기 때문에 정상적인 문서가 검색
    • search_keyword 인덱스가 있기 때문에 가능
    • search_keyword 인덱스가 없다면 오타 교정이 불가능
    PUT /search_keyword/_search
    {
    	"query": {
    		"match": {
    			"eng2kor_suggest": {
    				"query": "tkatjdwjswk"
    			}
    		}
    	}
    }
    
    PUT /search_keyword/_search
    {
    	"query": {
    		"match": {
    			"eng2kor_suggest": {
    				"query": "ㅑㅔㅙㅜㄷ"
    			}
    		}
    	}
    }
    

7.3 한글 키워드 자동완성

  • 자동완성을 지원하기 위해 Completion Suggest API를 제공
    • 한글을 처리는 안될 수 있음

7.3.1 Completion Suggest API를 이용한 한글 자동완성

1) 인덱스 생성

PUT /ac_test
{
	"settings": {
		"index": {
			"number_of_shards": 5,
			"number_of_replicas": 1
		}
	}
}

2) 매핑 설정

  • itemSrc
    • 매칭 검색 용도로 사용하는 필드
  • itemCompletion
    • 자동완성 용도로 사용하는 필드
    • type을 completion으로 설정
PUT /ac_test/_mapping/ac_test
{
	"properties": {
		"itemSrc": {
			"type": "keyword"
		},
		"itemCompletion": {
			"type": "completion"
		}
	}
}

3) 자동완성 데이터 색인

POST /ac_test/_bulk

{"index": {"_index": "ac_test", "_type": "ac_test", "_id": "1"}}
{"itemSrc": "신혼", "itemCompletion": "신혼"}

{"index": {"_index": "ac_test", "_type": "ac_test", "_id": "2"}}
{"itemSrc": "신혼가전", "itemCompletion": "신혼가전"}

{"index": {"_index": "ac_test", "_type": "ac_test", "_id": "3"}}
{"itemSrc": "신혼가전특별전", "itemCompletion": "신혼가전특별전"}

4) 자동완성 요청

  • itemSrc 필드를 이용한 일반 검색
  • GET /ac_test/_search { "query": { "match": { "itemSrc": "신혼" } } }
  • itemCompletion 필드를 이용한 검색
  • GET /ac_test/_search { "suggest": { "s1": { "prefix": "신혼", "completion": { "field": "itemCompletion", "size": 10 } } } }

7.3.2 Suggest API를 이용한 한글 자동완성 문제점

1) 부분 일치 불가

  • 가전”이란느 단어로 검색한다면?
    • 검색 결과는 0
    GET /ac_test/_search
    {
    	"suggest": {
    		"s1": {
    			"prefix": "가전",
    			"completion": {
    				"field": "itemCompletion",
    				"size": 10
    			}
    		}
    	}
    }
    
  • 내부적으로 Prefix 방식의 매칭만 지원하고 있음
  • 자동 완성 서비스를 제공하려면 키워드 기준 시작, 중간, 끝 등의 전방위 검색이 모두 가능해야 함

2) 한글 초성 검색 불가

  • 초성 검색이 가능해지려면 한글의 자모 분석이 먼저 이뤄져야 한다
  • Completion Suggest API를 이용해 자동완성을 구현할 경우 한글 자모 분석을 지원하지 않음
    • 초성 검색 불가능

3) 한글 자모 검색 불가

  • 키가 입력되는 도중에 유니코드가 순간적으로 변경 되다 보니 검색 결과가 나왔다가 안나왔다가 할 수 있다

7.3.3 직접 구현해보는 한글 자동 완성

  • Completion Suggest API에 의존하지 않고 직접 구현

7.3.3.1 루씬의 분석기능 활용

  • Completion Suggest API는 자동완성 기능은 빠른 속도를 보장해야 한다
    • 메모리를 적극적으로 활용
  • Completion Suggest API는 전체 데이터를 메모리에 올려 캐시로 생성하고 요청이 올 때마다 메모리 연산을 수행
  • 루씬이 제공하는 분석 기능은 메모리 연산은 아님
    • 속도 측면에서 일부 손해를 보게 된다.
  • Completion Suggest API를 이용하는 경우
    • 엘라스틱서치에서 자동완성을 위해 기본적으로 제공하는 기능
    • 제공되는 completion 키워드를 이용해 인덱스를 구현하면 바로 사용 가능
    • 데이터가 메모리에서 동작하기 때문에 매우 빠르다
    • 메모리에서 동작하므로 데이터 크기에 대한 제약이 있다
    • 현재는 전방일치 밖에 제공하지 않음
  • 루씬을 이용해 직접 구현하는 경우
    • 직접 구현해야 하므로 관련 지식이 필요
    • 루씬의 역색인 구조를 기반으로 동작하기 때문에 상대적으로 느리다
    • 사실상 데이터 크기에 제약이 없다
    • 루씬이 제공하는 분석기로 원하는 방식을 모두 구현할 수 있다.

7.3.3.2 확장된 Ngram 검색 적용

  • 부분일치를 가장 간단하게 구현하는 방법은 Ngram을 이용하는 것
  • 기본적으로 제공하는 분석기이기 때문에 손쉬운 사용 가능
  • Ngram은 단어 한 글자 한 글자 단위로 잘라내어 토큰화하기 때문에 누락 없는 부분일치를 구현하기에 안성맞춤

Ngram 분석기

  • 음절 단위로 토큰을 생성하기 때문에 재현율은 높으나 정확도는 떨어진다
  • 첫 음절을 기준으로 max_gram에 지정한 길이만큼 토큰을 생성
  • [p.358 페이지 참고]

Edge Ngram 분석기

  • 대부분 ngram과 유사하게 동작
  • 지정한 토크나이저의 특성에 따라 Ngram이 일어난다
  • [p.358 페이지 참고]

Edge Ngram Back Analyzer

  • Edge Ngram과 반대로 동작하는 토크나이저를 사용
  • 옵션으로 “side:back”을 반드시 지정 해야한다
  • [p.359 페이지 참고]

실습

1) 인덱스 생성

PUT /ac_test2
{
  "settings": {
    "index": {
      "number_of_shards": 5,
      "number_of_replicas": 1
    },
    "analysis": {
      "analyzer": {
        "ngram_analyzer": {
          "type": "custom",
          "tokenizer": "ngram_tokenizer",
          "filter": [
            "lowercase",
            "trim"
          ]
        },
        "edge_ngram_analyzer": {
          "type": "custom",
          "tokenizer": "edge_ngram_tokenizer",
          "filter": [
            "lowercase",
            "trim",
            "edge_ngram_filter_front"
          ]
        },
        "edge_ngram_analyzer_back": {
          "type": "custom",
          "tokenizer": "edge_ngram_tokenizer",
          "filter": [
            "lowercase",
            "trim",
            "edge_ngram_filter_back"
          ]
        }
      },
      "tokenizer": {
        "ngram_tokenizer": {
          "type": "nGram",
          "min_gram": "1",
          "max_gram": "50",
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "symbol"
          ]
        },
        "edge_ngram_tokenizer": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "symbol"
          ]
        }
      },
      "filter": {
        "edge_ngram_filter_front": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "side": "front"
        },
        "edge_ngram_filter_back": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "side": "back"
        }
      }
    }
  }
}

2) 매핑 설정

  • item
    • 일반적인 매칭 검색 용도로 사용
  • itemNgram
    • Ngram으로 분석된 정보를 자동완성으로 매칭하기 위한 필드
    • ngram_analyzer 분석기 사용
  • itemNgramEdge
    • Edge Ngram으로 분석된 정보를 자동완성으로 매칭하기 위한 필드
    • index_analyzer와 search_analyzer를 각각 다르게 설정
    • 색인할 때는 edge_ngram_analyzer 분석기 사용
    • 검색할 때는 ngram_analyzer 사용
  • itemNgramEdgeBack
    • Edge Ngram Back 으로 분석된 정보를 자동완성으로 매칭하기 위한 필드
    • index_analyzer와 search_analyzer를 각각 다르게 설정
    • 색인할 때는 edge_ngram_analyzer_back분석기 사용
    • 검색할 때는 ngram_analyzer 사용
PUT /ac_test2/_mapping/ac_test2
{
  "properties": {
    "item": {
      "type": "keyword",
      "boost": 30
    },
    "itemNgram": {
      "type": "text",
      "analyzer": "ngram_analyzer",
      "search_analyzer": "ngram_analyzer",
      "boost": 3
    },
    "itemNgramEdge": {
      "type": "text",
      "analyzer": "edge_ngram_analyzer",
      "search_analyzer": "ngram_analyzer",
      "boost": 2
    },
    "itemNgramEdgeBack": {
      "type": "text",
      "analyzer": "edge_ngram_analyzer_back",
      "search_analyzer": "ngram_analyzer",
      "boost": 1
    }
  }
}

3) 자동완성 데이터 색인

POST /ac_test2/_bluk
{
  "index": {
    "_index": "ac_test2",
    "_type": "ac_test2",
    "_id": "1"
  }
}
{
  "item": "신혼",
  "itemNgram": "신혼",
  "itemNgramEdge": "신혼",
  "itemNgramEdgeBack": "신혼"
}
{
  "index": {
    "_index": "ac_test2",
    "_type": "ac_test2",
    "_id": "2"
  }
}
{
  "item": "신혼가전",
  "itemNgram": "신혼가전",
  "itemNgramEdge": "신혼가전",
  "itemNgramEdgeBack": "신혼가전"
}
{
  "index": {
    "_index": "ac_test2",
    "_type": "ac_test2",
    "_id": "3"
  }
}
{
  "item": "신혼가전특별전",
  "itemNgram": "신혼가전특별전",
  "itemNgramEdge": "신혼가전특별전",
  "itemNgramEdgeBack": "신혼가전특별전"
}

4) 자동완성 요청

GET /ac_test2/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "prefix": {
            "item": "신혼"
          }
        },
        {
          "term": {
            "itemNgram": "신혼"
          }
        },
        {
          "term": {
            "itemNgramEdge": "신혼"
          }
        },
        {
          "term": {
            "itemNgramEdgeBack": "신혼"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}
  • 원하는 결과에서 랭킹을 추가
    • explain 파라미터를 추가해서 분석 가능
    GET /ac_test2/_search
    
    {
      "explain": true,
      "query": {
        "bool": {
          "should": [
            {
              "prefix": {
                "item": "신혼"
              }
            },
            {
              "term": {
                "itemNgram": "신혼"
              }
            },
            {
              "term": {
                "itemNgramEdge": "신혼"
              }
            },
            {
              "term": {
                "itemNgramEdgeBack": "신혼"
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    }
    

7.3.3.3 한글 초성 검색 적용하기

  • 토크나이저에서는 먼저 색인할 때 데이터를 자모 단위로 분해해서 토큰화
  • 한글은 자모 단위로 분해해서 초성만 추출
    • 추출한 내용을 ngram으로 분해
  • 자바카페 플러그인을 사용

1) 인덱스 생성

PUT /ac_test3
{
  "settings": {
    "index": {
      "number_of_shards": 5,
      "number_of_replicas": 1
    },
    "analysis": {
      "analyzer": {
        "chosung_index_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "javacafe_chosung_filter",
            "lowercase",
            "trim",
            "edge_ngram_filter_front"
          ]
        },
        "chosung_search_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "javacafe_chosung_filter",
            "lowercase",
            "trim"
          ]
        }
      },
      "tokenizer": {
        "edge_ngram_tokenizer": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "symbol"
          ]
        }
      },
      "filter": {
        "edge_ngram_filter_front": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "side": "front"
        },
        "javacafe_chosung_filter": {
          "type": "javacafe_chosung"
        }
      }
    }
  }
}

2) 매핑 설정

  • item
    • 일반적인 매칭 검색 용도로 사용하는 필드
  • itemChosung
    • 초성으로 분석된 정보를 자동완성으로 매칭하기 위한 필드
    • index_analyzer와 search_analyzer를 각각 다르게 설정
    • 색인할 때 chosung_index_analyzer 분석기 사용
    • 검색할 때 chosung_search_analyzer 분석기 사용
POST /ac_test3/_mapping/ac_test3
{
  "properties": {
    "item": {
      "type": "keyword",
      "boost": 30
    },
    "itemChosung": {
      "type": "text",
      "analyzer": "chosung_index_analyzer",
      "search_analyzer": "chosung_search_analyzer",
      "boost": 10
    }
  }
}

3) 자동완성 데이터 색인

POST /ac_test/_bulk
{
  "index": {
    "_index": "ac_test3",
    "_type": "ac_test3",
    "_id": "1"
  }
}
{
  "item": "신혼",
  "itemChosung": "신혼"
}
{
  "index": {
    "_index": "ac_test3",
    "_type": "ac_test3",
    "_id": "2"
  }
}
{
  "item": "신혼가전",
  "itemChosung": "신혼가전"
}
{
  "index": {
    "_index": "ac_test3",
    "_type": "ac_test3",
    "_id": "3"
  }
}
{
  "item": "신혼가전특별전",
  "itemChosung": "신혼가전특별전"
}

4) 자동완성 요청

GET /ac_test3/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "itemChosung": "ㅅㅎㄱㅈ"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

7.3.3.4 한글 자모 검색 적용

  • 자바카페 플러그인에 한글 자모를 분석할 수 있는 토크나이저가 포함되어 있다

1) 인덱스 생성

PUT /ac_test4
{
  "settings": {
    "index": {
      "number_of_shards": 5,
      "number_of_replicas": 1
    },
    "analysis": {
      "analyzer": {
        "jamo_index_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "javacafe_jamo_filter",
            "lowercase",
            "trim",
            "edge_ngram_filter_front"
          ]
        },
        "jamo_search_analyzer": {
          "type": "custom",
          "tokenizer": "keyword",
          "filter": [
            "javacafe_jamo_filter",
            "lowercase",
            "trim"
          ]
        }
      },
      "tokenizer": {
        "edge_ngram_tokenizer": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "symbol"
          ]
        }
      },
      "filter": {
        "edge_ngram_filter_front": {
          "type": "edgeNGram",
          "min_gram": "1",
          "max_gram": "50",
          "side": "front"
        },
        "javacafe_jamo_filter": {
          "type": "javacafe_jamo"
        }
      }
    }
  }
}

2) 매핑 설정

PUT /ac_test4/_mapping/ac_test4
{
  "properties": {
    "item": {
      "type": "keyword",
      "boost": 30
    },
    "itemJamo": {
      "type": "text",
      "analyzer": "jamo_index_analyzer",
      "search_analyzer": "jamo_search_analyzer",
      "boost": 10
    }
  }
}

3) 자동완성 데이터 색인

POST /ac_test4/_bluk
{
  "index": {
    "_index": "ac_test4",
    "_type": "ac_test4",
    "_id": "1"
  }
}
{
  "item": "신혼",
  "itemNgram": "신혼",
  "itemNgramEdge": "신혼",
  "itemNgramEdgeBack": "신혼"
}
{
  "index": {
    "_index": "ac_test4",
    "_type": "ac_test4",
    "_id": "2"
  }
}
{
  "item": "신혼가전",
  "itemNgram": "신혼가전",
  "itemNgramEdge": "신혼가전",
  "itemNgramEdgeBack": "신혼가전"
}
{
  "index": {
    "_index": "ac_test4",
    "_type": "ac_test4",
    "_id": "3"
  }
}
{
  "item": "신혼가전특별전",
  "itemNgram": "신혼가전특별전",
  "itemNgramEdge": "신혼가전특별전",
  "itemNgramEdgeBack": "신혼가전특별전"
}

4) 자동완성 요청

POST /ac_test4/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "itemJamo": "ㅅㅣㄴㅎ"
          }
        }
      ],
      "minimum_should_match": 1
    }
  }
}

7.4 자바카페 플러그인

  • 엘라스틱서치에서 제공하지 않는 기능을 추가하려면 플러그인을 사용 해야 함
  • 과거에는 엘라스틱서치에서 플러그인을 이용해 다양한 기능을 확장해서 사용하는 것을 권장
    • 최신 버전에서는 보안상의 이유로 많은 옵션들이 제거

7.4.1 한글 유니코드 이해

  • 유니코드에는 전 세계의 문자를 모두 표현하기 위해 다양한 영역이 있음
    • 한글은 0x0000 ~ 0xFFFF 영역 내부에 정의 됨

7.4.2 한글 자모 분석 필터

  • 한글을 자모 단위로 분해해서 제공하는 분석 필터

7.4.3 한글 초성 분석 필터

  • 한글을 자모 단위로 분해한 후 초성만 추출해서 제공하는 분석 필터
  • 기본적인 자모 분석과정은 javacafe_jamo 필터와 동일한 로직을 이용

7.4.4 영한 오타 변환 필터

  • 한영 키에 의한 영문 오타를 한글로 교정

7.4.5 한영 오타 변환 필터

  • 한글 오타를 영문으로 교정해주는 필터

7.4.6 스펠링 체크 필터

  • 맞춤법 검사기 내부에서 사용하는 필터
728x90

'검색엔진 스터디' 카테고리의 다른 글

05장 데이터 집계  (3) 2023.11.08
04장 데이터 검색  (1) 2023.11.08
03장 데이터 모델링  (1) 2023.11.08
02장 엘라스틱서치 살펴보기  (4) 2023.11.08
01장 검색 시스템 이해하기  (0) 2023.11.08