2018년 6월 25일 엔지니어링

엘라스틱서치 6.2를 이용한 한국어, 중국어, 일본어 검색 - 3부: Language Detector

By 김기주

이 글은 한국어, 중국어, 일본어 검색에 대한 3부작 중 마지막 글입니다. 만약 아직 1부를 읽지 않았다면 1부: 형태소 분석기부터 읽으시기 바랍니다. 엘라스틱서치 6.2를 이용한 한국어, 중국어, 일본어 검색 - 2부: Multi-fields에서는 멀티필드를 이용해서 다국어로 작성된 문서를 인덱싱하고 검색하는 방법을 살펴봤습니다. 하지만 하나의 텍스트를 언어에 상관 없이 4개의 필드에 저장하고 4개의 분석기로 분석하는 것은 시간과 저장공간의 낭비입니다. 이제 마지막으로 language detector를 이용해서 최적화해 보겠습니다. 텍스트는 역시 https://www.pyeongchang2018.com/ko/about-the-games에서 발췌했습니다.


Language detector

language detection용 ingest plugin(https://github.com/spinscale/elasticsearch-ingest-...)을 설치해서 시간과 저장공간을 절약하려고 합니다. 텍스트를 주 필드와 세 개의 서브필드로 인덱싱하는 대신, 아래 ingest pipeline의 langdetect processor는 “body” 필드의 언어를 감지해서 “language” 필드에 기록합니다. 그 다음 script processor는 “body” 필드의 내용을 언어별 필드(english_field, korean_field, japanese_field, or chinese_field)에 복사해서 분석합니다.


PUT _ingest/pipeline/langdetect-pipeline
{
  "description": "A pipeline to do whatever",
  "processors": [
    {
      "langdetect": {
        "field": "body",
        "target_field": "language"
      }
    },
    {
      "script": {
        "lang": "painless",
        "source": "if (ctx.language == 'ko') ctx.korean_field = ctx.body; if (ctx.language == 'ja') ctx.japanese_field = ctx.body; if (ctx.language == 'zh-cn') ctx.chinese_field = ctx.body; if (ctx.language == 'en') ctx.english_field = ctx.body;"
      }
    }
  ]
}

이 블로그에서는 kuromoji, smartcn, openkoreantext-analyzer를 이용하므로, 아래 인덱스를 만들기 전에 이들 플러그인을 설치해야 합니다.


DELETE test2
PUT /test2
{
  "mappings": {
    "docs": {
      "properties": {
        "body": {
          "type": "text"
        },
        "english_field": {
          "type": "text"
        },
        "korean_field": {
          "analyzer": "openkoreantext-analyzer",
          "type": "text"
        },
        "japanese_field": {
          "analyzer": "kuromoji",
          "type": "text"
        },
        "chinese_field": {
          "analyzer": "smartcn",
          "type": "text"
        }
      }
    }
  }
}

문서를 인덱싱할 때는 language detector를 사용하도록 “langdetect-pipeline” 파이프라인을 지정해야 합니다.


PUT /test2/docs/1?pipeline=langdetect-pipeline
{
  "body" : "The XXIII Olympic Winter Games will be held for 17 days from 9 to 25 February 2018 in PyeongChang, Gangwon Province, the Republic of Korea. PyeongChang was selected as the host city of the 2018 Olympic Winter Games after receiving a majority vote at the 123rd IOC Session held on 6 July 2011 after three consecutive bids. The Olympic Winter Games will be held in Korea for the first time in 30 years after the Seoul Olympic Games in 1988. PyeongChang will be the stage for the Opening and Closing Ceremonies and most snow sports. Alpine speed events will take place in Jeongseon, and all ice sports will be competed in the coastal city of Gangneung."
}
PUT /test2/docs/2?pipeline=langdetect-pipeline
{
  "body" : "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
}
PUT /test2/docs/3?pipeline=langdetect-pipeline
{
  "body" : "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
}
PUT /test2/docs/4?pipeline=langdetect-pipeline
{
  "body" : "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
}

예를 들어, “body” 필드의 내용이 한국어이면, 아래와 같이 “korean_field”로 복사됩니다.


GET /test2/docs/2
=>
{
  "_index": "test",
  "_type": "docs",
  "_id": "2",
  "_version": 1,
  "found": true,
  "_source": {
    "language": "ko",
    "body": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다.",
    "korean_field": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
  }
}

멀티필드를 사용했을 때와 비슷한 검색 결과를 얻을 수 있습니다. 결과를 필터링하기 위해 source filtering을 사용했습니다.

한국어

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "올림픽대회",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.57860667,
    "hits": [
      {
        "_index": "test",
        "_type": "docs",
        "_id": "2",
        "_score": 0.57860667,
        "_source": {
          "body": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
        }
      }
    ]
  }
}

영어

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "Olympic Games",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.97953933,
    "hits": [
      {
        "_index": "test",
        "_type": "docs",
        "_id": "1",
        "_score": 0.97953933,
        "_source": {
          "body": "The XXIII Olympic Winter Games will be held for 17 days from 9 to 25 February 2018 in PyeongChang, Gangwon Province, the Republic of Korea. PyeongChang was selected as the host city of the 2018 Olympic Winter Games after receiving a majority vote at the 123rd IOC Session held on 6 July 2011 after three consecutive bids. The Olympic Winter Games will be held in Korea for the first time in 30 years after the Seoul Olympic Games in 1988. PyeongChang will be the stage for the Opening and Closing Ceremonies and most snow sports. Alpine speed events will take place in Jeongseon, and all ice sports will be competed in the coastal city of Gangneung."
        }
      }
    ]
  }
}

일본어

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "オリンピック大会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.7469032,
    "hits": [
      {
        "_index": "test2",
        "_type": "docs",
        "_id": "4",
        "_score": 0.7469032,
        "_source": {
          "body": "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
        }
      }
    ]
  }
}

중국어

POST /test2/_search
{
  "query": {
    "multi_match": {
      "query": "奥运会",
      "fields": [
        "english_field",
        "korean_field",
        "chinese_field",
        "japanese_field"
      ]
    }
  },
  "_source": "body"
}
=>
...
  "hits": {
    "total": 1,
    "max_score": 0.49148652,
    "hits": [
      {
        "_index": "test2",
        "_type": "docs",
        "_id": "3",
        "_score": 0.49148652,
        "_source": {
          "body": "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
        }
      }
    ]
  }
}

주목할 것은 일본어 키워드로 검색하면 일본어 문서만 리턴되고, 중국어 키워드로 검색하면 중국어 문서만 리턴된다는 것입니다. 이는 엘라스틱서치 6.2를 이용한 한국어, 중국어, 일본어 검색 - 2부: Multi-fields와 다른데, 언어별 분석기로 분석된 필드만 검색하기 때문입니다.


시간이 더 걸리진 않을까요?

인덱싱이나 쿼리에 걸리는 시간이 걱정된다면, 멀티필드나 language detector를 이용해서 인덱싱하는 데 걸리는 시간은 단일 필드를 이용할 때보다 약간 더 길지만 큰 차이는 없습니다.



그림 1 500개의 문서를 인덱싱하는 데 걸리는 시간(맥북 프로, 2.9 GHz 인텔 코어 i7, 16GB 2133 MHz LPDDR3)


멀티필드나 language detector를 이용해서 쿼리하는 데 걸리는 시간은 단일 필드를 이용할 때와 거의 같습니다.



그림 2 쿼리를 500번 실행하는 데 걸리는 시간(맥북 프로, 2.9 GHz 인텔 코어 i7, 16GB 2133 MHz LPDDR3)


Language detector를 이용하면, 멀티필드를 쓸 때보다 좋은 쿼리 결과를 얻을 수 있고 저장공간도 절약할 수 있습니다. 엘라스틱서치 6.x에는 심지어 “Sparse Field Improvements” (Space Saving Improvements in Elasticsearch 6.0 참고)도 포함되어 있습니다.


부록

multi-lang-scripts.zip

  • index.sh - 인덱싱 시간 측정 스크립트
  • query.sh - 쿼리 시간 측정 스크립트