【翻訳】Elasticsearchにおけるマッピングの更新
背景
オープンソースの検索エンジンといえばSolr!というイメージで、Solrしか使ったことがなかったんですが、作りたいアプリケーションの都合で今回はElasticsearchを使ってみることにしました。わからないことばかりでTwitterでぼやいてたんですが
まさかのアドバイスを頂いてすごく嬉しかったので、該当箇所を翻訳してみました。
オリジナル
Elasticsearch: The Definitive Guide Mapping
https://www.elastic.co/guide/en/elasticsearch/guide/current/mapping-intro.html#updating-a-mapping
翻訳
マッピングの更新
最初にインデックスを作成するときには、タイプに対してマッピングを指定することができる。あるいは新しく定義するタイプに対して後からマッピングを追加(また、既存のタイプのマッピングを更新)することができる。このとき、/_mapping
エンドポイントを利用する。
既存のマッピングに対しては、「追加」することはできるが、「変更」することはできない。もしマッピングに対して既にフィールドが存在するのなら、そのフィールドにはデータがインデックスされているだろう。フィールドのマッピングを変更するのなら、既にインデックスされているデータは間違いとなり、適切に検索できなくなる。
新しいフィールドを追加するためにマッピングを更新することはできるが、既存のフィールドをanalyzed
からnot_analyzed
に変更することはできない。
マッピングを指定する2つの方法をデモで示すために、まずはgb
インデックスを削除する。
DELETE /gb
そして新しいインデックスを作成する。ここではenglish
アナライザを利用するtweet
フィールドを指定する。
PUT /gb { "mappings": { "tweet" : { "properties" : { "tweet" : { "type" : "string", "analyzer": "english" }, "date" : { "type" : "date" }, "name" : { "type" : "string" }, "user_id" : { "type" : "long" } } } } }
ここではマッピングと共にインデックスを作成している。
その後で、not_analyzed
なテキストフィールドであるtag
フィールドをtweet
マッピングに追加する。ここでは_mapping
エンドポイントを利用する。
PUT /gb/_mapping/tweet { "properties" : { "tag" : { "type" : "string", "index": "not_analyzed" } } }
このとき、既存のフィールドの全ての定義をもう一度列挙する必要はない(既に変更はできないため)。新しく追加するフィールドは、既存のマッピングにマージされる。
まとめ
太字と下線で強調した部分がすべてで、既にドキュメントを追加したなら後から変更するのは難しい。DBのテーブル定義なんかだと中のデータ入れ替えとかもっと面倒だし、そもそもきっちり想定をして設計するのが重要なんだと思います。
余談
マッピングの変更のたびに再インデックスが必要なら、本番環境のシステムも毎回止めないといけないのかというのが一番の疑問だったんですが、ドキュメントでも言及されてました。
Changing Mapping with Zero Downtime | Elastic
すんごいタイムリーな記事も。
techlife.cookpad.com
インデックスにエイリアスを貼る機能を使って、裏で新しく作りなおしたインデックスと入れ替えることで実現するようです。マスターとスレーブを駆使してごにょごにょ切り替えたりはしなくていいのね。