Skip to main content

Elasticsearch 7.3 활용해보기 #5 – 한글검색

index이름/_search 를 이용한 한글 검색을 해보도록 합시다. 이게 참 단어가 인덱싱이 잘되어있어야 검색이 되는데, #4에서 봤던 userdict_ko.txt 같은 파일에 고유명사나 분해되면 안되는 단어들은 잘 기록해두도록 해야 합니다.

한글처리가 가능한 index 생성

검색을 하기위한 환경을 만들어봅니다. kibana console에 한글 처리가 가능한 index를 생성하기위해서 다음 쿼리를 console에 복붙(!!) 해봅니다.

PUT my_index
{
  "settings":{
      "number_of_shards":1,
      "number_of_replicas":0,
      "index":{
        "analysis":{
          "tokenizer":{
            "nori_tokenizer_mixed_dict":{
              "type":"nori_tokenizer",
              "decompound_mode":"mixed",
              "user_dictionary":"userdict_ko.txt"
            }
          },
          "analyzer": {
            "korean":{
              "type":"custom",
              "tokenizer":"nori_tokenizer_mixed_dict",
              "filter":[
                "nori_readingform","lowercase",
                "nori_part_of_speech_basic"]
              }
            },
            "filter":{
              "nori_part_of_speech_basic":{
                "type":"nori_part_of_speech",
                "stoptags":["E","IC","J","MAG","MAJ","MM","SP","SSC","SSO","SC","SE","XPN","XSA","XSN","XSV","UNA","NA","VSV"]
          }
        }
      }
    }
  }
}

생성되었다는 메시지를 확인하시고..

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "my_index"
}

대량 데이터 추가(bulk api)

대량(??)의 데이터를 5개 정도 추가해봅시다. 서버에서 해도 되지만, console에 직접 추가해도 잘 되더군요 ^^ 다만 데이터 부분은 한라인에 다 적어야 한다는 점은 주의해야 할 것 같습니다. -_- 모양땜에 엔터를 좀 넣어줬더니 잘 작동 안하더군요.

POST my_index/_bulk
{ "index":{} }
{ "title" : "청산별곡", "note" : "살어리 살어리랏다 靑山에 살어리랏다. 멀위랑 달래 먹고 靑山에 살어리랏다.얄리얄리 얄랑셩 얄라리 얄라" }
{ "index":{} }
{ "title" : "가시리", "note" : "가시리 가시리잇고 나는 버리고 가시리잇고 나는 위 증즐가 大平盛代 " }
{ "index":{} }
{ "title" : "정과정", "note" : "내 님을 그리워하여 울고 있으니 산 접동새와 내 신세가 비슷합니다." }
{ "index":{} }
{ "title" : "西京별곡", "note" : "西京이 아즐가 西京이 셔울히 마르는 위 두어렁셩 두어렁셩 다링디리" }
{ "index":{} }
{ "title" : "쌍화점", "note" : "만두가게에 만두 사러 갔더니 회회아비가 내 손목을 쥐었더라." }

이외에도 일괄적으로 업데이트 및 삭제도 가능하니 다음 자세한 내용을 참고하세요.
(자세한 내용: https://www.elastic.co/guide/en/elasticsearch/reference/7.3/docs-bulk.html )

추가된 데이터를 확인해보면….

GET my_index/_search
{
  "took" : 506,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "Dt4MH20BjjMy29Rvz-kp",
        "_score" : 1.0,
        "_source" : {
          "title" : "청산별곡",
          "note" : "살어리 살어리랏다 靑山에 살어리랏다. 멀위랑 달래 먹고 靑山에 살어리랏다.얄리얄리 얄랑셩 얄라리 얄라"
        }
      },
~~~~ 생략함 ~~~~~

“total” : “value” : 5, 로 잘 들어간것으로 나옵니다.

한글 검색해보기

이제부터 한글을 검색해봅시다. 여러가지 쿼리가 있고 검색 방법이 있지만 다음 쿼리를 통해 검색해봅시다. 검색할 필드를 지정해주고 query에 검색어를 넣어줍니다. 해당하는 단어가 찾아지게 하기 위해서 *(wildcard)를 넣어주었습니다. 뿐만 아니라 AND 와 OR를 지원하여 상세히 검색할 수 있씁니다.

GET my_index/_search
{
  "query": {
    "query_string": {
      "fields": ["title","note"],
      "query": "*얄리*"
    }
  }
}
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_index",
        "_type" : "_doc",
        "_id" : "Dt4MH20BjjMy29Rvz-kp",
        "_score" : 1.0,
        "_source" : {
          "title" : "청산별곡",
          "note" : "살어리 살어리랏다 靑山에 살어리랏다. 멀위랑 달래 먹고 靑山에 살어리랏다.얄리얄리 얄랑셩 얄라리 얄라"
        }
      }
    ]
  }
}

여담이지만 -_- 요구 스팩에 맞춰서 서비스를 이렇게 만들었는데 별로 안빠른거 같에서 고민이 많아집니다. query_string 말고 match_all 등의 쿼리를 참조하면 좀더 빠른 검색이 가능할 것 같습니다.

(참고: https://www.elastic.co/guide/en/elasticsearch/reference/7.3/search.html )

오늘은 여기까지…..

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.