はじめに
業務で、Elasticsearchに入ってるデータをちょうだい!と言われて、Elasticsearchに入れたときのデータをそのまま渡せばいいのだが、実態がそれと違うかもだし、Elasticsearchからでもデータを抜けるだろうと試してできたコマンド
準備
- Elasticsearch 1.7.1
- jq 1.3
- JSONの操作と言えば、やはりこれ。
- csvkit 0.9
- csvkitは、JSONから簡単にCSVに変換できるコマンドなどが入ったCSVについて便利な操作ができるツール。詳しくは公式ドキュメント
- curl
- 入ってるよね?
1行コマンド
curl -XGET "[IPアドレス or ホスト名]:[ポート番号]/[index名]/[type名]/_search?&size=[抽出したいレコード数]" | jq [.hits.hits[]._source] | in2csv -f json
例えば、nginxのアクセスログデータでちょっとやってみた。アドレスとかは適当な値に変換してる。
$ curl -XGET "[IPアドレス]:[ポート番号]/nginxaccess-2015.10.16/nginx/_search?&size=2" | jq [.hits.hits[]._source] | in2csv -f json
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1478 100 1478 0 0 48481 0 --:--:-- --:--:-- --:--:-- 50965
@timestamp,status,query_string,uri,https,request_uri,request_length,request_method,remote_addr,bytes_sent,body_bytes_sent,referer,useragent,forwardedfor,request_time,upstream_response_time,@nginx.access
2015-10-16T10:35:24+09:00,200,-,/~hogehoge.user/img/title.gif,,/~hogehoge.user/img/title.gif,511,GET,192.168.42.1,16445,16204,http://hogehoge.com,User-HogeAgent,::ffff:192.168.43.1,0.000,-,nginx.access
2015-10-16T10:21:17+09:00,404,-,/favicon.ico,,/favicon.ico,563,GET,192.168.42.1,726,571,http://hogehoge.com,User-HogeAgent,"::ffff:192.168.43.1,0.000,-,nginx.acces
解説
Elasticsearch
- REST API的な操作が可能なのはすでにご存知だと思います。
- [index名]と[type名]を記入し、_searchで検索
- デフォルトだと10レコードだけしか表示されないので、欲しいレコード数分だけ、sizeで指定する
そもそもindex名がわからない
以下でElasticsearchにあるindex一覧を取得できる。
$ curl -XGET [IPアドレス or ホスト名]:[ポート番号]/_aliases?pretty
そもそもType名がわからない
下記例では、index名が「nginxaccess-*」のnginxのログの例。mappingから「nginx」がType名と分かる。
$ curl -XGET [IPアドレス or ホスト名]:[ポート番号]/nginxaccess-*/_mapping?pretty=true
{
"nginxaccess-2015.10.09" : {
"mappings" : {
"nginx" : {
"properties" : {
"@nginx.access" : {
"type" : "string"
},
"@timestamp" : {
"type" : "date",
"format" : "dateOptionalTime"
},
<snip>
そもそもどれくらいレコード入ってるのかわからない
_countでも分かります。_searchでも分かる。
$ curl -XGET [IPアドレス or ホスト名]:[ポート番号]/nginxaccess-*/nginx/_count?pretty
そもそもどんな風にレコードが保存されているかわからない
なにもいじってなければ、以下の感じで入ってるかと。hits -> hits -> _source の中が実際のデータ。
$ curl -XGET [IPアドレス or ホスト名]:[ポート番号]/nginxaccess-2015.10.16/nginx/_search?&pretty&size=2"
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"failed" : 0
},
"hits" : {
"total" : 145,
"max_score" : 1.0,
"hits" : [ {
"_index" : "nginxaccess-2015.10.16",
"_type" : "nginx",
"_id" : "AVBuSYiyx-w4SUTcVChQ",
"_score" : 1.0,
"_source":{"remote_addr":hogehoge ....}
}, {
"_index" : "nginxaccess-2015.10.16",
"_type" : "nginx",
"_id" : "AVBuPKMsx-w4SUTcVCfh",
"_score" : 1.0,
"_source":{"remote_addr":hogehoge ....}
} ]
}
}
クエリも投げたい
"q="で指定する。OR検索は、"|"を入れる。
$ curl -XGET [IPアドレス or ホスト名]:[ポート番号]/nginxaccess-2015.10.16/nginx/_search?&q=remote_addr:172.16.1.1|172.16.1.2"
jq
- jq自体のドキュメントは日本語だと、軽量JSONパーサー『jq』のドキュメント:『jq Manual』をざっくり日本語訳してみましたが詳しく翻訳してくれている。英語が読めるならもちろん公式ドキュメントが良い。
in2csv
- csvkitツールのコマンドの1つ。-f オプションで指定したフォーマットを入力として、csv形式に変換してくれる。
- 参考は以前自分が書いたcsvkitの使い方まとめ
おわりに
- もともとは、pythonのElasticsearch APIを使おうと思ったが、jqとcsvkit強いなと思って、結局Linuxコマンドで。
- rubyでcsvを抽出するやつなどもあるようです。Elasticsearch の検索結果を csv に書き出すスクリプトを作った。