elasticsearchのMapping conflictを解消する
Elasticsearchでfieldのtypeでコンフリクトが発生したときに自分が解消するまでにやった手順を書きます。
今回はコンフリクトを解消する上でElasticsearchのパース機能を利用するため、パースできないデータは切り捨てます。たとえば、"100" -> 100 はパースできますが"100MB" -> 100 はパースできません。このやり方で通用する場合は何か参考になるかもしれません。
環境
- Windows 10
- Elasticsearch 7.3.0
- Kibana 7.3.0
前準備
今回は説明のために意図的にコンフリクトするようなダミーデータを作ります。以下のクエリをKibanaのdev toolsで実行します。
POST _bulk
{ "index" : { "_index" : "test1", "_id" : "1" } }
{ "name" : "aaa", "num": 100 }
{ "create" : { "_index" : "test1", "_id" : "2" } }
{ "name" : "bbb", "num": 200 }
{ "index" : { "_index" : "test2", "_id" : "1" } }
{ "name" : "aaa", "num": "100" }
{ "create" : { "_index" : "test2", "_id" : "2" } }
{ "name" : "bbb", "num": "200B" }
この状態で Management/Index Patterns にて「test*
」で Create index pattern します。
test*
を開くと以下の画像のようにMappingがコンフリクトしてると警告が出ると思います。num
のTypeがconflictになっていることが確認できたら成功(?)です。
以上で前準備としては終了です。次にコンフリクトを解消する手順です。
手順
今回はnum
をlong
にする方向でコンフリクトを解消します。そのため、test2
のMappingを修正する必要があります。しかし、ElasticsearchにはMappingを修正する機能は存在しないらしくindexを作り直すしかないそうです。そのためtest2
を別のindexにいったんコピーして逃がしておいて、正しいTypeでMappingし直したtest2
に再度コピーするという方法をとります。
1. test2の一時保存用Mappingの作成
この時コンフリクトしているfieldのTypeを明示的に指定します。今回はnumのTypeをlongに指定します。
PUT tmp-test2
{
"mappings": {
"properties": {
"num": {
"type": "long"
}
}
}
}
2. 一時保存先に中身をコピー
_reindexはあるindexの内容を別のindexにコピーするElasticsearchのAPIです。failuresが出ると思いますが、これはnum
が200B
のdocumentが原因で出ているものです。冒頭で説明した通り今回の方法ではこのようにElasticsearchがパースできない値は切り捨てます。
POST _reindex
{
"source": {
"index": "test2"
},
"dest": {
"index": "tmp-test2"
}
}
// RETURN
// {
// "took": 41,
// "timed_out": false,
// "total": 2,
// "updated": 0,
// "created": 1,
// "deleted": 0,
// "batches": 1,
// "version_conflicts": 0,
// "noops": 0,
// "retries": {
// "bulk": 0,
// "search": 0
// },
// "throttled_millis": 0,
// "requests_per_second": -1,
// "throttled_until_millis": 0,
// "failures": [
// {
// "index": "tmp-test2",
// "type": "_doc",
// "id": "2",
// "cause": {
// "type": "mapper_parsing_exception",
// "reason": "failed to parse field [num] of type [long] in document with id '2'. Preview of field's value: '200B'",
// "caused_by": {
// "type": "illegal_argument_exception",
// "reason": "For input string: \"200B\""
// }
// },
// "status": 400
// }
// ]
// }
3. test2のindexを削除
削除するのが怖い場合はsnapshotなどを活用してバックアップをとってください。今回はsnapshotについては書きませんので以下の記事などを参考にしてください。
https://qiita.com/okaru/items/82b1ee5d249c3dc01452
DELETE test2
4. test2のMappingを作成
PUT test2
{
"mappings": {
"properties": {
"num": {
"type": "long"
}
}
}
}
5. 一時保存先からtest2に中身をコピー
POST _reindex
{
"source": {
"index": "tmp-test2"
},
"dest": {
"index": "test2"
}
}
6. 一時保存先を削除
DELETE tmp-test2
7. test* で Refresh field list
Management/Index Patternにいってtest*
をクリック、右上のリロードっぽいボタンを押して Refresh field list します。
8. コンフリクト解消🙌
さいごに
Discoverでtest*
を見てみましょう。データが3つしかありません。test2
の_id2のドキュメントはパースすることができなかったため、_reindexでコピーされなかったからです。注意してください。
間違い・もっと良い方法などありましたらご指摘いただけると嬉しいです。
この記事が誰かの役に立てば幸いです。
質問は@mn_choromeまで。
参考
Author And Source
この問題について(elasticsearchのMapping conflictを解消する), 我々は、より多くの情報をここで見つけました https://qiita.com/chorome/items/e1506c8c8c1f94ddfb21著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .