エンジニアリング

Elasticsearch 6.2で中国語や日本語、韓国語の文字列を検索する - その1:Analyzer

著者

平昌で開催された2018年の冬季オリンピックには92か国が参加し。パラリンピックには49か国の選手が出場しました。たとえばElasticでも、現在34か国で社員が従業しています。グローバル化がますます進展し、日頃やりとりするメールに他の言語が含まれていることも珍しくなくなりました。今回は、韓国語の単語「올림픽대회」を含むメールを検索する方法をご紹介します。

複数の言語で書かれたドキュメントを扱う方法については以前に https://www.elastic.co/guide/en/elasticsearch/guide/current/language-intro.html (英文のみ)でも取り上げていますが、この記事はカスタムプラグインを必要としないヨーロッパ言語が主体のドキュメントのケースでした。この記事では、韓国語、日本語、中国語向けのカスタムプラグイン(各言語のAnalyzer)をご紹介します。

デフォルトのStandard Analyzerとは

全文検索には各言語用のAnalyzerが必要です。しかしデフォルトのStandard Analyzerは中国語や日本語、韓国語の文字列検索に最適ではありません。まず、Standard Analyzerを韓国語、日本語、中国語に使用するとどのようなことが起きるか見てみましょう。なお、テキストは平昌オリンピックからの抜粋です。

[韓国語]

POST _analyze
{
  "analyzer": "standard",
  "text": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
}
=>
{
  "tokens": [
    {
      "token": "제23회",
      "start_offset": 0,
      "end_offset": 4,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "동계올림픽대회는",
      "start_offset": 5,
      "end_offset": 13,
      "type": "<HANGUL>",
      "position": 1
    },
…

韓国語は言語学上「膠着語」に分類され、「동계올림픽대회」のような名詞は、「는」のような後置詞を伴うことが普通です。精度の高い検索を行うには、こうした後置詞を区別するか、除外することが望ましいのですが、Standard Analyzerは名詞と後置詞を区分できません。

[日本語]

POST _analyze
{
  "analyzer": "standard",
  "text": "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
}
=>
{
  "tokens": [
    {
      "token": "第",
      "start_offset": 0,
      "end_offset": 1,
      "type": "<IDEOGRAPHIC>",
      "position": 0
    },
    {
      "token": "23",
      "start_offset": 1,
      "end_offset": 3,
      "type": "<NUM>",
      "position": 1
    },
    {
      "token": "回",
      "start_offset": 3,
      "end_offset": 4,
      "type": "<IDEOGRAPHIC>",
      "position": 2
    },
    {
      "token": "冬",
      "start_offset": 4,
      "end_offset": 5,
      "type": "<IDEOGRAPHIC>",
      "position": 3
    },
    {
      "token": "季",
      "start_offset": 5,
      "end_offset": 6,
      "type": "<IDEOGRAPHIC>",
      "position": 4
    },
    {
      "token": "オリンピック",
      "start_offset": 6,
      "end_offset": 12,
      "type": "<KATAKANA>",
      "position": 5
    },
    {
      "token": "大",
      "start_offset": 12,
      "end_offset": 13,
      "type": "<IDEOGRAPHIC>",
      "position": 6
    },
    {
      "token": "会",
      "start_offset": 13,
      "end_offset": 14,
      "type": "<IDEOGRAPHIC>",
      "position": 7
    },
    {
      "token": "は",
      "start_offset": 14,
      "end_offset": 15,
      "type": "<HIRAGANA>",
      "position": 8
    },
…

日本語もやはり「膠着語」に属し、「冬季オリンピック大会」のような名詞の後に、通常「は」のような後置詞を伴います。 日本語でも、精度の高い検索を行うには、後置詞を区別する、または除外することが望ましいのですが、Standard Analyzerは対応していません。さらにStandard Analyzerは、漢字とかなを併記する単語の場合、漢字1字を1つのtokenとして扱ってしまいます。

[中国語]

POST _analyze
{
  "analyzer": "standard",
  "text": "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
}
=>
{
  "tokens": [
    {
      "token": "第",
      "start_offset": 0,
      "end_offset": 1,
      "type": "<IDEOGRAPHIC>",
      "position": 0
    },
    {
      "token": "23",
      "start_offset": 1,
      "end_offset": 3,
      "type": "<NUM>",
      "position": 1
    },
    {
      "token": "届",
      "start_offset": 3,
      "end_offset": 4,
      "type": "<IDEOGRAPHIC>",
      "position": 2
    },
    {
      "token": "冬",
      "start_offset": 4,
      "end_offset": 5,
      "type": "<IDEOGRAPHIC>",
      "position": 3
    },
    {
      "token": "季",
      "start_offset": 5,
      "end_offset": 6,
      "type": "<IDEOGRAPHIC>",
      "position": 4
    },
    {
      "token": "奥",
      "start_offset": 6,
      "end_offset": 7,
      "type": "<IDEOGRAPHIC>",
      "position": 5
    },
    {
      "token": "运",
      "start_offset": 7,
      "end_offset": 8,
      "type": "<IDEOGRAPHIC>",
      "position": 6
    },
    {
      "token": "会",
      "start_offset": 8,
      "end_offset": 9,
      "type": "<IDEOGRAPHIC>",
      "position": 7
    },
...

Standard Analyzerは、中国語の冬季オリンピック、「冬季奥运会」も1単語として認識できません。

各言語のAnalyzer:カスタムプラグイン

それぞれの言語に特化したAnalyzerを使用すると、検索の精度は向上します。日本語ならkuromoji、中国語ではsmartcn、韓国語は openkoreantext-analyzer というAnalyzerがよく使われています。 次の例を実行するには、はじめにクラスターのすべてのノードにこのAnalyzerをインストールする必要があります。openkoreantext-analyzerはElasticのリポジトリではホストされていませんので、URLをすべて入力するか、あらかじめダウンロードしてください。

[韓国語]

POST _analyze
{
  "analyzer": "openkoreantext-analyzer",
  "text": "제23회 동계올림픽대회는 대한민국 강원도 평창에서 2018년 2월 9일부터 25일까지 17일간 개최됩니다. 대한민국 평창은 세 번의 도전 끝에 지난 2011년 7월 6일 열린 제123차 IOC 총회에서 과반 표를 획득하며 2018년 동계올림픽 개최지로 선정되었습니다. 이로써 대한민국에서는 1988년 서울 올림픽 이후 30년 만에, 평창에서 개∙폐회식과 대부분의 설상 경기가 개최되며, 강릉에서는 빙상 종목 전 경기가, 그리고 정선에서는 알파인 스키 활강 경기가 개최될 예정입니다."
}
=>
{
  "tokens": [
    {
      "token": "제",
      "start_offset": 0,
      "end_offset": 1,
      "type": "Noun",
      "position": 0
    },
    {
      "token": "23회",
      "start_offset": 1,
      "end_offset": 4,
      "type": "Number",
      "position": 1
    },
    {
      "token": "동계올림픽",
      "start_offset": 5,
      "end_offset": 10,
      "type": "Noun",
      "position": 2
    },
    {
      "token": "대회",
      "start_offset": 10,
      "end_offset": 12,
      "type": "Noun",
      "position": 3
    },
...

後置詞がすべて除外されています。

[日本語]

POST _analyze
{
  "analyzer": "kuromoji",
  "text": "第23回冬季オリンピック大会は大韓民国江原道平昌で2018年2月9日から25日までの17日間、開催されます。大韓民国・平昌は三度の挑戦の末、2011年7月7日に開かれた第123回IOC総会で過半数票を獲得し、2018年冬季オリンピック及びパラリンピックの開催地に選ばれました。これにより1988年ソウルオリンピック開催後30年の時を経てついに、大韓民国で最初の冬季パラリンピックの舞台が繰り広げられます。平昌で開・閉会式とほぼ全ての雪上競技が開催され、江陵では氷上種目全競技が、そして旌善ではアルペンスキー滑降競技が開催される予定です。"
}
=>
{
  "tokens": [
    {
      "token": "第",
      "start_offset": 0,
      "end_offset": 1,
      "type": "word",
      "position": 0
    },
    {
      "token": "23",
      "start_offset": 1,
      "end_offset": 3,
      "type": "word",
      "position": 1
    },
    {
      "token": "回",
      "start_offset": 3,
      "end_offset": 4,
      "type": "word",
      "position": 2
    },
    {
      "token": "冬季",
      "start_offset": 4,
      "end_offset": 6,
      "type": "word",
      "position": 3
    },
    {
      "token": "オリンピック",
      "start_offset": 6,
      "end_offset": 12,
      "type": "word",
      "position": 4
    },
    {
      "token": "大会",
      "start_offset": 12,
      "end_offset": 14,
      "type": "word",
      "position": 5
    },
...

後置詞がすべて除外され、漢字がバラバラになっていません。

[中国語]

POST _analyze
{
  "analyzer": "smartcn",
  "text": "第23届冬季奥运会将于2018年2月9日-25日在韩国江原道平昌展开。韩国平昌在第三次申奥之后,于2011年7月6日召开的第123届国际奥委会全会上被选定为2018年冬季奥运会的主办地。由此,韩国自1988年举办首尔夏季奥运会以后,时隔30年,将首次举办冬季奥运会。该届冬奥会的开·闭幕式以及大部分的雪上运动将在平昌进行,而所有冰上运动将在江陵、高山滑雪滑降比赛则将在旌善进行。"
}
=>
{
  "tokens": [
    {
      "token": "第",
      "start_offset": 0,
      "end_offset": 1,
      "type": "word",
      "position": 0
    },
    {
      "token": "23",
      "start_offset": 1,
      "end_offset": 3,
      "type": "word",
      "position": 1
    },
    {
      "token": "届",
      "start_offset": 3,
      "end_offset": 4,
      "type": "word",
      "position": 2
    },
    {
      "token": "冬季",
      "start_offset": 4,
      "end_offset": 6,
      "type": "word",
      "position": 3
    },
    {
      "token": "奥运会",
      "start_offset": 6,
      "end_offset": 9,
      "type": "word",
      "position": 4
    },
...

文字が単語の単位でまとまっています。

これで、韓国語、日本語、中国語の文字列を分析することが可能になりました。次の記事、「Elasticsearch 6.2で中国語や日本語、韓国語の文字列を検索する - その2:マルチフィールド」では、韓国語、日本語、中国語文字列のインデックス作成とクエリの方法をご紹介します。