Elasticsearch で SQL の update みたいな事をする
SQL の update みたいなことがしたい
Elasticsearch (以下ES) は RDB じゃないってのは理解しつつも、場合によっては SQL での update 文みたいな事がしたい。
現状だと、scan & scroll → Update API でドキュメントを1つ1つ更新する、みたいな事しかできない。
PRがあるがマージされていない
同じことを考えている人は多いみたいで、ググると、ちょくちょくESの issue tracker に同じような内容で登録されている(これとか)。で、PRとかも投げられてるけど、
「”update” 処理は長時間かかる場合も多いけど、途中で止める仕組みがないので」
みたいな理由でマージされていない。
プラグイン
で、それをプラグインとしてリリースした人がいた。偉い。
セットアップ
インストールとかはまぁ普通通りやればいいので省略。
ただ、elasticsearch.yml で以下を記述しなければいけない。
script.disable_dynamic: false
これはイマイチ・・・
使い方
READMEから抜粋。
curl -XPOST 'localhost:9200/twitter/_update_by_query' -d ' { "query" : { "term" : { "message" : "you" } }, "script" : "ctx._source.likes += 1" }'
これは、SQLに翻訳すると、こんな感じ。
-- 実際は twitter は RDB で言う「データベース」に相当するけど・・・ UPDATE twitter SET likes = likes + 1 WHERE message like '%you%';
ファイルからも読み込めるようにPR作った
インラインでスクリプトを書いて実行させるのはさすがに抵抗があるので、ファイルから読み込めるようにPRを送った。
マージして欲しいなー。マージされなければ、fork版をリリースしよう。
使い方
スクリプトファイルは scripts ディレクトリの下に保存する。パッケージで入れると /etc/elasticsearch/scripts の下になるのかな。スクリプトは Groovy で書く。他の言語もプラグインを入れれば OK っぽいけど、そこまでしたくないし。
スクリプトは foo.groovy だとする。
以下のように実行。
curl -XPOST 'localhost:9200/twitter/_update_by_query' -d ' { "query" : { "term" : { "message" : "you" } }, "script_file": "foo", "lang": "groovy" }'
script_file には拡張子無しのファイル名を、lang で groovy を指定するのがポイント。
まとめ
プラグインを使うと、Elasticsearch でも SQL の update みたいな処理が出来る。インデックスが大きいと時間がかかるので注意が必要。