弱いエンジニアの備忘録

自分的に気になった技術に関するメモや備忘録です。Elasticsearchに関する記事が多くなりそうです。

elasticsearchのfieldを一部修正する

概要

elasticesearchに入れたデータを後で修正したくなった時の修正手順。
update by queryを使います。

バージョン情報など

elasticsearch-6.0.0-alpha2
kibana-6.0.0-alpha2

前提

ユーザーのアカウント情報を持つaccountというindexを作成しました。

fieldの内容としては、氏名や電話番号、住所などが入っています。
f:id:shin0higuchi:20170707004947p:plain

「ユーザーの増加にともなってuser_idの見直しが必要になった」というシチュエーションを想定します。(先見性の無さ....)

新たなユーザー、yokohama takashiさんが登録されましたが、このユーザーのuser_idが既存のユーザーと被ってしまいました。
もともとuser_idの命名規則が、「firstnameの頭文字」.「lastname」だったので、idが被らないように変更する必要があります。
f:id:shin0higuchi:20170707005401p:plain

user_idで検索すると2件ヒットしてしまいます。
f:id:shin0higuchi:20170707005801p:plain

この記事では、t.yokohamaのuser_idを、
lastname.firstnameの形式に書き換える手順を書きます。

手順

1. 変更したいドキュメントの条件をqueryで定義する。

今回は取り急ぎ、t.yokohamaというuser_idを持つユーザーのuser_idのみを変更します。
そのためqueryは下記のようになります。

"query": {
    "term": {
      "user_id.keyword": {
        "value": "t.yokohama"
      }
    }
  }

2. update by query

結論から書くと、下記のjsonをConsole上で実行すれば、updateができます。

POST account/_update_by_query
{
  "query": {
    "term": {
      "user_id.keyword": {
        "value": "t.yokohama"
      }
    }
  },
  "script": {
    "inline": "ctx._source.user_id = ctx._source.firstname + '.' + ctx._source.lastname",
    "lang": "painless"
  }
}

query部分で、対象とするドキュメントを絞り、script部分で処理の内容を書きます。
scriptではpainlessを使っているので、ctx._source.field名でフィールドにアクセスできます。

これを実際に実行すると...
f:id:shin0higuchi:20170707010639p:plain

無事書き換わりました
f:id:shin0higuchi:20170707010659p:plain

めでたしめでたし

その他メモ

・reindex APIでもscriptが使えるので、部分的に書き換えて別indexに入れることもできる。

追記(10/1)

reindex APIを使った方法も追記して欲しいとのコメントをいただいたので追記します。

下記のようなリクエストを実行すれば同じようなことができます。
(queryの部分を省けば、全ドキュメントを対象にできます。)

POST _reindex
{
  "source": {
    "index": "account"
  },
  "dest": {
    "index": "account_dest"
  }, 
  "script": {
    "inline": "ctx._source.user_id = ctx._source.firstname + '.' + ctx._source.lastname",
    "lang": "painless"
  }
}

※この場合、account indexが書き換えられるのでは無く、account_destという別のindexが作成されるので、もう一度reindex APIで元のindexに書き戻すか、aliasを利用してください。