https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping.html を読んでまとめました。
対象読者
例によって主に自分
Mappingとは?
ElasticsearchはDocumentの登録時に合わせてindexを作成する。そのindexをどのように登録するのかを定義するのがMappingである。(RDBだとMappingはテーブルスキーマにあたる)。Mappingは下記の用途に使われる。
- どの文字列フィールドが全文検索の対象か?
- どのフィールドが数値、日付、geolocationか?
- documentの複製である _all フィールドをインデックス化するかどうか?
- 日付の形式は?
- 動的に追加されるフィールドのマッピング
Mapping Types
Documentを論理的なグループに分けるため、indexにはいくつかの Mapping Types がある。例えばユーザーのDocumentであればuser
型、ブログの投稿だったらblogpost
型になるように定義できる。
Mapping typeとは、Meta-fields及びFieldsと、propatiesだ。
Meta-fields
Documemtに関係するメタデータについてどのように扱うのかをカスタマイズするのがMeta-fieldsだ。Meta-fieldsに含まれるのは例えば _index、 _type、_id、 _source だ。
Fields or properties
型は field と property を定義でき、どのようにマッピングするかをMapping typeに定義する。 user
型であれば title
、name
、そしてage
を持ち、blogpost
型であればtitle
とbody
、user_id
等を持つ、などだ。同一 index 内にある同一名のFieldは同じようにマッピングされなければならない。
フィールド名に .
を使う時の注意:
Elasticserch 2.4では .
を許容するようになったが、 利用には注意が必要 、とのこと。
Field のデータ型
フィールドには下記のようなデータ型がある。
- string, date, long, double, boolean, ipなどのシンプルな型
- JSONのような構造を持つ性質のための object, nested型
- nested型はarrayのようなobjectを複数持つ時に使う。Luceneは中にオブジェクトを持つようなコンセプトがないので、Elasticsearchがフラットにデータを保持できるように間をとりもつ。
- geo_pointや geo_shape、completion などの特殊型
- geo_pointやgeo_shapeは位置情報、 completionは前方一致につかう情報を保持する型。
string型のフィールドでもanalyzedとすれば全文検索に使えるが、not_analyzedとするとソートや集約に使える。また、stringフィールドにanalyzerを指定することでどう分かち書きするかを指定できる。
fieldsにmulti-fieldsがあるのは上記をうまくサポートするため。
Dynamic mapping
FieldやMapping typeは利用し始めるまでに定義されなければならない、というわけではない。 ここで登場するのが Dynamic mapping。ドキュメントにindex作成始まるとともに自動的にmapping typeとFieldを定義する。
Dynamic mappingの作成ルールもカスタマイズできる。
明示的にMappingするには?
使い始めはElasticsearchが自動的に推測してくれる。それでもいくらかは明示的にMappingを指定したくなるだろう。
fieldやMapping typeの定義はインデックスの作成時の他、既存のindexに指定するなら PUT mapping API を使うとよい。
既存の Mapping を更新するには?
既存のtype及びmappingは更新できない。Mappingを変更することとはIndexの再作成を意味する。新しくindexを作り、データをreindexする。
Mapping typeはFieldの内容を共有する
Mapping typeは Field のグループ化に使われる。しかし Mapping type の各々の Field は独立していない。
- 同じ名前で
- 同じindexにあり
- 異なるmapping typeだと
- 内部的には同じfieldにマップされるので
- 同じマッピングを持たなければならない
user
と blogpost
mapping typeにはtitle
というフィールドがあった。そのため、 title
フィールドは各々の型から同じマッピングをされなければならない。例外として copy_to
、 'dynamic'、enabled
、 properties
などのパラメータはフィールドごとに設定できる。
もし問題があるようであれば、user_title
やblog_title
と指定するとよい。
余談
ElasticsearchのRubyのクライアントには Elasticsearch::Persistence というgemを本家が作っているのでそれを使うとよさげ