diadia

興味があることをやってみる。自分のメモを残しておきます。

elasticsearchで日本語を検索できるようにする

(elasticsearchで検索される英単語と検索されない英単語について - diadiaに続いて)

じゃあ日本語も同じように単語ごとに空白で区切ってから登録すればElasticsearchが使えるねって発想になると思う。しかし生の日本語文章を単語に区切る前処理(この場合では日本語文章の単語と単語の間にスペースを加える自作のスクリプトを実行する)をしてからデータを登録するのは手軽にelasticsearch使えなくて嫌な感じになる。

でもそこで悩む必要はない。そもそもElasticsearchでは単語を識別するための基準がスペース(white space)ではない。単語に区切る基準は、tokenizerと呼ばれ、Tokenizerにどう単語を識別するかを設定して上げれば別の方法で文章から単語を区切ることができる。言い換えれば、tokenizerに日本語文章から日本語単語を識別しますというtokenizerを設定してやればそれで済む話なのです。

(補足ですが英文の場合tokenizerを設定していないですが、デフォルトでスペースを基準に単語に分けるtokenizerが設定されているので英文はtokenizerを明示的にセットしなくても英文章から単語を識別できていた)

日本語文章から単語に区切るtokenizerはkuromoji_tokenizerという。コレはpluginという形で使うので別途インストールが必要になる。 インストールは以下のように実行する。

// elasticsearchのbinディレクトリにて
./elasticsearch-plugin install analysis-kuromoji

Japanese (kuromoji) Analysis Plugin | Elasticsearch Plugins and Integrations [7.11] | Elastic

日本語文章も検索できるようにする

ここでは生の日本語文章を前処理なしでそのままエラスティックサーチに保存させて、日本語の単語から検索できるようにする方法と、それが本当にできるのかを検証する。

// tokenizerに日本語単語を識別するkuromoji_tokenizerを使ったインデックスを作成する
PUT sample2
{ 
  "settings":{
    "analysis": {
      "analyzer": {
        "my_kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer"
        }
      }
    }
  },
  "mappings":{
    "properties": {
      "content":{
          "type":"text",
          "analyzer": "my_kuromoji_analyzer"
        }
    }
  }
}
// 日本語文章を登録します
// 結果を先にいうと単語と識別されるのは"野菜", "を", "育てる", "お", "ばあちゃん"って事になりました。

PUT sample2/_doc/1
{
  "content":"野菜を育てるおばあちゃん"
}

検索してみる。

// なので、ちゃんで検索をかけると検索結果は無しとなります。
// 育てるのみヒットし、育つではヒットしません。これに対応する方法もあります。

GET sample2/_search
{
  "query":{
    "match":{
      "content":"ちゃん"
    }
  }
}

"野菜", "を", "育てる", "お", "ばあちゃん"で検索をかけると結果が得られます。 しかしながら、"ちゃん"や"育つ"また"野"では検索結果はえられない結果になります。
このことから日本語文章から適切に単語を識別して、転置索引するようになっていると確認する事ができました。
補足、kuromoji_tokenizerだけでは日本語の単語識別は不完全でicu_normalizerというものも使うことをドキュメントには書かれています。

kuromoji analyzer | Elasticsearch Plugins and Integrations [7.11] | Elastic