elasticsearchのデータのタイムスタンプを一括更新する


やりたいこと

前回の話
GrafanaのOverride rerative time機能でelasticsearchのデータを常時表示するためには、
elasticsearchのデータのタイムスタンプを、全データ更新するシェルが必要になる。
ということで今回はその作成記事。

elasticsearchで一括置換するクエリ

下記を参考に一括更新のクエリを調べる。
https://qiita.com/nakazii-co-jp/items/d8dca15e5eab6406ffdb

サイトにあったクエリを少し変えて、Hogeのとこを日時にすればいけると想定。

curl -XPOST 'http://localhost:9200/hoge_index/_update_by_query?conflicts=proceed&pretty' -d '{
  "query": {
    "match_all": { }
  },
  "script": {
    "inline": "ctx._source.field_01 = \"Hoge\";"
  }
}'

curlに変数をどうやって入れるのか?

$DATEとか作ってdateコマンドの結果を入れるも、jsonのエラーとか出てうまくいかない。
変数がうまく展開されない。

下記を参考にシングルクォートが問題と判明。ヒアドキュメントを使うことにした。
これはいい方法だと思った。
https://qiita.com/tekitoh/items/8acccb313d6e7a14c2ec
https://dev.classmethod.jp/server-side/os/how-to-inject-variable-to-json-on-bash/

ヒアドキュメント使ってもなんかフォーマットエラーが出る。

elasticsearchの日時(date)のフォーマットではまる

細部は違うけど、下記と同じフォーマットエラーが出る。
https://stackoverflow.com/questions/48916830/elasticsearch-date-format-parsing-error
上記から引用したエラー

"type": "mapper_parsing_exception",
        "reason": "failed to parse [afield.startDate]",
        "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "Invalid format: \"2018-01-10T07:07:07+01:00\" is malformed at \"+01:00\""
        }

調べた結果、どうも下記のdateのフォーマットが
elasticsearchの対応パターンになかったためらしい。
下記のフォーマットでlogstashでelasticsearchに問題なく取り込んでいたから中々気づけなかった

date -d "+%Y-%m-%d %H:MM:ss"

公式へのリンク
https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html

完成したシェル

いろいろ試行錯誤した結果、下記でうまく@timestampを全データ指定の時間に更新できました。
これをcronで動かして@timestampが直近の1時間になるようにしています。
※'9 hours ago'はelasticsearchのtimezoneを合わせてないので、その分ずらしているため

#!/bin/sh

DATE=`date -d '9 hours ago' "+%Y-%m-%dT%H:00:00.000Z"`

curl -XPOST "localhost:9200/hoge_index/_update_by_query?conflicts=proceed&pretty" -d @- <<EOS
{
 "query": { "match_all": {}},
 "script": { "inline": "ctx._source['@timestamp'] = ['$DATE'];" }
}
EOS