Elasticsearchでmappingを更新して日本語対応する
今作っているシステムで、全文検索部分にElasticsearchを採用した。理由は、使ったことなかったので触ってみたかったから。
環境はElasticsearch 1.4
インストールとか
ドキュメント見ればいいので、省略。RedHat系の場合もUbuntuの場合も、パッケージを使えばいいと思う。
データを入れてみる
「へー。スキーマとか定義しなくても、勝手にデータ型とか定義してくれるんだ。でも日本語はどうするんだろう?まぁ後で変更すればいっか。」
とこの辺を読んで思った。
データの投入の仕方はcurlを使う場合はこんな感じ。ちなみに、そのページの最初にも書いてあるけど、以下の用語については最初に覚えておかないとドキュメントを読むときに困る。
- Index -> RDBにおけるdatabase
- Type -> RDBにおけるtable
- Document -> RDBにおけるrow
- Field -> RDBにおけるcolumn
データを投入すると、勝手にfieldとかが定義される。
日本語対応
さて、このままだとデフォルトの設定(?)なので、string型にたいする日本語の検索とかが上手く出来ない。日本語対応について解説したサイト・ページはいくつもあるので、それを参考に設定する必要がある。
自分が見たページを挙げておく。
※後者は浅井さんが書いてるってのに最後で気づいた。
ま、LuceneとかSolrを少しでも触ったことがあれば、それらのページを読めば問題なくセットアップ出来ると思う。
既存インデックスのマッピングの更新
で、既に定義されているマッピングを日本語対応のマッピングに更新したい。
流れ
要はalter table …. alter column …. みたいなことをやりたいんだけど、indexに既にデータが入っていると、マッピングの変更とかは出来ないらしい。
方法としては、ドキュメントのこちらによると
- 現indexに対するalias作成
- 新規index作成(新しいマッピングで)
- 現indexから新indexにデータコピー
- aliasを新indexに対して付け替え
らしい。2〜4を”in a single atomic step”でやれば、”zero downtime”とのこと。
自分の場合、開発中のサービスなのでzero downtimeにはこだわらないからどうでもいいけど、元のドキュメントだと3をどうやってやれば良いか書いていない。
こちらのドキュメントだとscan & scrollで古いindexからデータを取得して、bulk APIで新しいインデックスに投入せよとのこと。How?
インデックスのコピー
結局、reindexというプラグインを使うことにした。内部的にはscan & scroll -> bulk APIらしい。
が、これがES 1.4.0に対応していないので、やっつけで対応してpull requestを送ってみた。
pluginのインストールはドキュメントを見てもらうとして、自分がどうやって使ったかというと
古いindexからマッピング情報の取得
curl -XGET 'localhost:9200/oldindex/_mapping/?pretty' > mapping.json
mapping.jsonを編集
新しいインデックスを、新しいマッピング情報で作成
curl -XPUT 'localhost:9200/newindex' --data-binary "@/path/to/new-mapping.json"
データのコピー(pluginの機能)
curl -XPUT 'http://localhost:9200/newindex/_reindex?searchIndex=oldindex'
後は必要に応じてaliasを作成したり、古いの削除したり。
まとめ
日本語対応するためには、最初からちゃんとマッピング定義しといたほうが良い(テンプレートを使った方法とかは省略)。
後から定義を変更するには、新しくインデックスを作成し、そこに古いインデックスからデータをコピーする必要がある。その際に、reindexプラグインが使える。
こんくらい標準機能で用意してくれないのかなーというのが感想。