elasticsearch の API のレスポンスみたいな、深くネストした json は俯瞰で見づらいので、フラットにして眺めるための手順。
あるいは jq の --stream
オプションの使い方。
元のjson
ここから拝借。
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html
a.json
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.3862944,
"hits": [
{
"_index": "twitter",
"_type": "_doc",
"_id": "0",
"_score": 1.3862944,
"_source": {
"user": "kimchy",
"message": "trying out Elasticsearch",
"date": "2009-11-15T14:12:12",
"likes": 0
}
}
]
}
}
キーを辿る
ついでに leaf node を抽出。
$ cat a.json | jq -c --stream 'select(length==2)'
[["took"],1]
[["timed_out"],false]
[["_shards","total"],1]
[["_shards","successful"],1]
[["_shards","skipped"],0]
[["_shards","failed"],0]
[["hits","total","value"],1]
[["hits","total","relation"],"eq"]
[["hits","max_score"],1.3862944]
[["hits","hits",0,"_index"],"twitter"]
[["hits","hits",0,"_type"],"_doc"]
[["hits","hits",0,"_id"],"0"]
[["hits","hits",0,"_score"],1.3862944]
[["hits","hits",0,"_source","user"],"kimchy"]
[["hits","hits",0,"_source","message"],"trying out Elasticsearch"]
[["hits","hits",0,"_source","date"],"2009-11-15T14:12:12"]
[["hits","hits",0,"_source","likes"],0]
key をフラットにする
$ cat a.json | jq -c --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}'
{"key":"took","value":1}
{"key":"timed_out","value":false}
{"key":"_shards.total","value":1}
{"key":"_shards.successful","value":1}
{"key":"_shards.skipped","value":0}
{"key":"_shards.failed","value":0}
{"key":"hits.total.value","value":1}
{"key":"hits.total.relation","value":"eq"}
{"key":"hits.max_score","value":1.3862944}
{"key":"hits.hits.0._index","value":"twitter"}
{"key":"hits.hits.0._type","value":"_doc"}
{"key":"hits.hits.0._id","value":"0"}
{"key":"hits.hits.0._score","value":1.3862944}
{"key":"hits.hits.0._source.user","value":"kimchy"}
{"key":"hits.hits.0._source.message","value":"trying out Elasticsearch"}
{"key":"hits.hits.0._source.date","value":"2009-11-15T14:12:12"}
{"key":"hits.hits.0._source.likes","value":0}
全体を1階層に寄せる
いったん1件ずつ出力したのをパイプに流して jq --slurp
で受けるのがコツ。
$ cat a.json | jq --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}' | jq -s from_entries
{
"took": 1,
"timed_out": false,
"_shards.total": 1,
"_shards.successful": 1,
"_shards.skipped": 0,
"_shards.failed": 0,
"hits.total.value": 1,
"hits.total.relation": "eq",
"hits.max_score": 1.3862944,
"hits.hits.0._index": "twitter",
"hits.hits.0._type": "_doc",
"hits.hits.0._id": "0",
"hits.hits.0._score": 1.3862944,
"hits.hits.0._source.user": "kimchy",
"hits.hits.0._source.message": "trying out Elasticsearch",
"hits.hits.0._source.date": "2009-11-15T14:12:12",
"hits.hits.0._source.likes": 0
}
おまけ:1行ずつ出力して fuzzy finder に流すとか
$ cat a.json | jq -c --stream 'select(length==2)|{key: .[0]|join("."), value: .[1]}' | fzf