※この記事は次のブログを翻訳したものになります。タイプとフィールドのマッピングに関する多義性です。インデックスの故障やデータのロスを結果として引き起こします。多くの変更を費やしました。新しいルールを強制し、これまでのインデックスに関しては後方互換性を保つようにします。コンフリクトなどが存在するため、それらを利用できないです。v2.0にはアップグレードできません。これらのインデックスのデータが必要ない場合は、インデックスを消せばいいです。ない場合はマッピングを正しくして再度インデックスする必要があるでしょう。マッピングを正しく変更することは、私たちが簡単に決めることではありません。ここからは、現在ある問題点と、私たちがどのように実装して解決したかについて説明します。フィールドマッピングのコンフリクトあいまいなフィールドのルックアップタイプのメタフィールドアナライザ設定index_nameとpath同期的なマッピングの更新マッピングの削除2.0のための準備フィールドマッピングのコンフリクトこれまで、わたしたちはドキュメントのタイプは「データベースのテーブルのようなもの」と説明していました。タイプの目的を説明する簡単な方法だったからです。残念なことにこれは、真実ではありません。内部的に、Luceneのフィールド名が同じものになります。Elasticsearchは同じLuceneのフィールドに数値と文字列のデータをもつことになります。インデックスが破損することになります。この問題を解決するために、まず、ドキュメントタイプの名前をフィールドの名前の前に追加することを考えました。各フィールドは完全に別のものとなります。このアプローチの利点はドキュメントタイプが実際のテーブルのようになることです。この方法には多くの欠点があります。ドキュメントタイプを前につける必要があります。複数のドキュメントタイプに対して同じフィールド名で検索する場合、クエリを個別に発行しなければならなく遅くなります。多くの検索で、既存の多くのクエリを壊してしまうために、単純なmatchやtermクエリの代わりに、multi-fieldクエリを使う必要があります。圧縮の効率の悪さから、ヒープ利用量、ディスク使用量、I/Oなどが、増加します。同じインデックスの同じ名前を持つ全てのフィールドは、同じマッピングを持つ必要があるというルールを採用することに決めました。copy_toやenabledのようなパラメータはタイプごとに指定することができるようになっています。これにより、データの破損、クエリ時の例外そして、おかしな結果が発生する問題を防ぎます。クエリとaggregationは現在でも高速なままで、圧縮率を最大化し、ヒープ使用量やディスク使用率の低減させます。この解決方法の欠点は、個別のテーブルとしてタイプを扱いたいユーザが彼らの考え方を変える必要があるということです。これは、思ったよりも問題ではありません。実際には、多くのフィールド名はデータの明確なタイプを表現しています。created_dateは常に、日付ですし、number_of_hitsフィールドはいつも数値です。フィールドマッピングがコンフリクトしているユーザはデータを失ったり、おかしなデータを受け取ったり、データを欠損させています。ベストプラクティスにユーザが従っているかどうかによらず、インデックス時に正しい振る舞いを強制することが現在の違いです。そこにはいくつかの解決方法があります。タイプの代わりにインデックスを別々に最も簡単な解決方法です。インデックスを別々のインデックスとし、実際のデータベーステーブルのようにします。ソートやaggregationも同じデータタイプへのクエリのように動作します。これまでと同じ制限です。コンフリクトしたフィールドの名前の変更コンフリクトがごくわずかな場合、(Logstashやアプリケーションで使っているものも一緒に)よりわかりやすいフィールド名に変更することで解決できます。2つのerrorフィールドがあった場合に、error_codeとerror_messageに変更します。異なるドキュメントタイプのフィールドは別々のcopy_toを設定できます。特定のタイプだけ、errorフィールドの値を数値のerror_codeフィールドにコピーすることができます。}}他のタイプでは文字列のerror_messageにコピーします。}}同様の解決方法としてmulti-fieldも使えます。各データタイプに対してネストしたフィールドにときどき、Elasticsearchに送ったドキュメントやドキュメントがもっているフィールドを制御できない場合があります。部分的なコンフリクトに加え、闇雲に、ユーザが送ってきたフィールドを受け入れると、マッピングが肥大化します。タイムスタンプやIPアドレスをフィールド名に使うようなドキュメントがあると考えてください。フィールドにすることで、str_val、int_val、date_valというような各データタイプを利用できます。"2015-06-01"}アプリケーションによって、次のようにフォーマットしなおす必要があります。]}この解決方法は、アプリケーションサイドでより多くの作業が必要ですが、コンフリクトの問題とマッピングの肥大化の問題を同時に解決します。name”、フルパス、ドキュメントタイプを前につけたフルパスが利用できます。これらのオプションがあいまいさをもたらしています。サンプルとして次のマッピングをご覧ください。}}titleはuser.title、blog.title、blog.user.titleのどれでしょう?user.titleはuser.titleまたはblog.user.titleのどちらでしょう?答えは「場合によります。Elasticsearchが最初に見つけたものになります。フィールドはリクエストごとに変わるため、各ノードでマッピングがどのようにシリアライズされたかに依存します。2.0では、フィールドを指定する時に、ドキュメントタイプを除いたフルパス名を使用するべきでしょう。user.titleは、blogタイプのuser.titleを意味します。titleは、userとblogタイプのtitleフィールドを意味します。*titleはuser.titleとtitleフィールドの両方にマッチします。userタイプのtitleフィールドとblogタイプのtitleの違いはどのように指定するのでしょう?指定できません。titleフィールドは両方のタイプで同じフィールドになります。本質的にtitleと呼ばれる1つのフィールドになります。user.やblog.のようなタイプのプレフィックスはタイプを指定することによるフィルタリングで効果があります。クエリのblog.titleフィールドはblogタイプのドキュメントだけを検索し、userタイプのドキュメントを検索しません。このシンタックスは誤解を招きやすいです。いつでも動作するわけではないからです。aggregationやsuggestionはすべてのタイプに関する結果を含みます。この利用のため、上記の例のあいまいさがあるので、タイプのプレフィックスはサポートしません。nameやタイププレフィックスを利用したpercolatorは更新する必要があります。タイプのメタフィールドすべてのタイプはメタフィールドを持っています。_id、_index、_routing、_parent、_timestampなどです。これらのほとんどはindex、store、pathのような幾つかの設定をサポートしています。これらの設定について次のようにシンプルにしました。_idと_typeは変更不可_indexは、ドキュメントのもつインデックスを保存するためにenabled_routingはrequiredのみを指定_sizeはenabledのみ_timestampはデフォルトで保存される_boostと_analyzerは廃止。古いインデックスのものは無視されるドキュメントのフィールドから_idと_routingと_timestampの値を抽出することができました。この機能は廃止されます。これは、ドキュメントのパースとコンフリクトを起こすためです。stringで指定可能です。_boostと_analyzerフィールドは例外で、すでにあるメタフィールドの設定は古いインデックスのものが採用されます。それぞれのレベルで指定可能でした。chainの組み合わせができることにより、おかしな関連度を引き起こしていました。フィールドマッピングのコンフリクトを解消することに加え、アナライザの設定も簡略化します。Analyzedな文字列フィールドは、analyzer設定とsearch_analyzer設定(analyzer設定の値をデフォルトとする)を指定できます。index_analyzer設定はanalyzerとなります。複数のタイプで同じ名前のフィールドがある場合、フィールドはすべて、同じアナライザの設定を持たなければなりません。タイプレベルのデフォルト設定のanalyzer、index_analyzer、search_analyzer設定は廃止されます。デフォルトアナライザはインデックスごとにインデックスのanalysis設定で設定します。これらはdefaultもしくはdefault_searchという名前で設定します。ドキュメントごとの_analyzerフィールドはサポートしません。既存のインデックスのものは無視されます。v1.0.0から利用できる)copy_toによって置き換わりました。既存のインデックスについてはこれらは機能しますが、新しいインデックスでは指定できません。フィールドはローカルのマッピングに追加され、それから、マスターに変更(新しいマッピングをすべてのシャードに適用する更新)が送信されていました。同時に2つのシャードに同じフィールドを追加することができます。そのとき、異なる2つのマッピングがある可能性があります。1つはdoubleでもう1つはlongだったり、stringとdateだったりと。このような場合、マスターに最初に届いたマッピングが採用されます。これを利用し続けます。そのご、ノードをリスタートしたときに、シャードが別のノードに移動し、マスターにあるマッピングを適用します。このとき、インデックスが破損したりデータを失ったりします。これを防ぐために、シャードはインデキシングを続ける前に、新しいマッピングがマスターによって採用されるかどうかを待つようになりました。これはすべてのマッピングが安全に更新されます。新しいフィールドをもっているドキュメントをインデキシングすると、前よりも処理が遅くなるでしょう。受け入れられることを待つ必要があるためです。クラスタの状態の更新処理のスピードが次の2つの新しい機能によって大きく改善されています。クラスタ状態の差分:可能であれば、クラスタの状態の変更はクラスタ状態全体の変更ではなく、部分的なものとする。割り当てられていないシャードのコピーの日付が最新のものを持っているかを見つけるために、リクエストをデータノードに対して送信します。ここで、クラスタ状態を変更する呼び出しがブロッキングで行われていました。v1.6.0から、このリクエストはバックグラウンドで非同期で実行されます。これにより、マッピング更新のようなペンディングタスクをより早く処理できるようになります。マッピングの削除(そのタイプのドキュメントがある場合)タイプマッピングを削除できないようにします。後から同じ名前のフィールドが追加されたときにインデックスの破損を引き起こします。そのようなマッピングは残しておくか、新しいインデックスに再インデックスすることができます。2.0のための準備マッピングがコンフリクトしているかどうかを決めることは、手動で行うには慎重に行う必要があります。Pluginを提供します。これは、2.0で非推奨になったり廃止された機能を利用しているかどうかを見つけるために役に立つでしょう。必要ないなら削除します。これらのコンフリクトを解決しない限り2.0にはアップグレードできないでしょう。