json是elasticsearch响应的内容,有多个aggregation就会有多级buckets,数据字段无法提前预知。
```json
{
"took": 596,
"timed_out": false,
"_shards": {
"total": 11,
"successful": 11,
"failed": 0
},
"hits": {
"total": 1121497,
"max_score": 0,
"hits": []
},
"aggregations": {
"day.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "20170418",
"doc_count": 1121497,
"channel.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "channel01",
"doc_count": 901649,
"acttype.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "show",
"doc_count": 424711,
"ct": {
"value": 143760
}
},
{
"key": "click",
"doc_count": 253006,
"ct": {
"value": 114883
}
},
{
"key": "install",
"doc_count": 139527,
"ct": {
"value": 68115
}
},
{
"key": "installed",
"doc_count": 84405,
"ct": {
"value": 49037
}
}
]
}
},
{
"key": "channel02",
"doc_count": 107639,
"acttype.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "show",
"doc_count": 50364,
"ct": {
"value": 17019
}
},
{
"key": "click",
"doc_count": 32334,
"ct": {
"value": 14123
}
},
{
"key": "install",
"doc_count": 19891,
"ct": {
"value": 9259
}
},
{
"key": "installed",
"doc_count": 5050,
"ct": {
"value": 2922
}
}
]
}
},
{
"key": "channel03",
"doc_count": 69671,
"acttype.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "show",
"doc_count": 26617,
"ct": {
"value": 8229
}
},
{
"key": "click",
"doc_count": 22793,
"ct": {
"value": 7812
}
},
{
"key": "install",
"doc_count": 19919,
"ct": {
"value": 6165
}
},
{
"key": "installed",
"doc_count": 342,
"ct": {
"value": 290
}
}
]
}
},
{
"key": "channel04",
"doc_count": 42511,
"acttype.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "show",
"doc_count": 22565,
"ct": {
"value": 8044
}
},
{
"key": "click",
"doc_count": 11601,
"ct": {
"value": 5890
}
},
{
"key": "install",
"doc_count": 7208,
"ct": {
"value": 3802
}
},
{
"key": "installed",
"doc_count": 1137,
"ct": {
"value": 761
}
}
]
}
},
{
"key": "channel05",
"doc_count": 27,
"acttype.raw": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [
{
"key": "show",
"doc_count": 20,
"ct": {
"value": 7
}
},
{
"key": "click",
"doc_count": 7,
"ct": {
"value": 2
}
}
]
}
}
]
}
}
]
}
}
}
```
最终能解析成二维数组,输出表格。
如
```
+--------------+-----------+----+----+
| day | channel| acttype | ct |
+--------------+-----------+----+----+
| cloudmonitor | * | 1 | 1 |
| mysql.sys | localhost | 1 | 1 |
| root | 192.% | 1 | 1 |
| root | localhost | 1 | 1 |
+--------------+-----------+----+
4 rows in set (0.00 sec)
```
写了一个很长很长的,不知道行不行。
```
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"os"
)
type Root struct {
Took int `json:"took"`
Timeout bool `json:"timed_out"`
Shards Shard `json:"_shards"`
Hits Hit `json:"hits"`
Aggregations Aggregation `json:"aggregations"`
}
type Shard struct {
Total int `json:"total"`
Successful int `json:"successful"`
Failed int `json:"failed"`
}
type Hit struct {
Total int `json:"total"`
MaxScore int `json:"max_score"`
Hits []Hit `json:"hits"`
}
type Aggregation struct {
DR DayRaw `json:"day.raw"`
}
type DayRaw struct {
Dceub int `json:"doc_count_error_upper_bound"`
Sodc int `json:"sum_other_doc_count"`
Buckets []DayBucket `json:"buckets"`
}
type DayBucket struct {
Key string `json:"key"`
Dc int `json:"doc_count"`
ChanRaw ChannelRaw `json:"channel.raw"`
}
type ChannelRaw struct {
Dceub int `json:"doc_count_error_upper_bound"`
Sodc int `json:"sum_other_doc_count"`
Buckets []ChanBucket `json:"buckets"`
}
type ChanBucket struct {
Key string `json:"key"`
Dc int `json:"doc_count"`
ActtRaw ActtypeRaw `json:"acttype.raw"`
}
type ActtypeRaw struct {
Dceub int `json:"doc_count_error_upper_bound"`
Sodc int `json:"sum_other_doc_count"`
Buckets []ActtBucket `json:"buckets"`
}
type ActtBucket struct {
Key string `json:"key"`
Dc int `json:"doc_count"`
Ct Ct `json:"ct"`
}
type Ct struct {
Value int `json:"value"`
}
func main() {
f, err := os.Open("json.log")
checkErr(err)
data, err := ioutil.ReadAll(f)
checkErr(err)
var root Root
err = json.Unmarshal(data, &root)
checkErr(err)
result, err := json.MarshalIndent(&root, "", " ")
checkErr(err)
fmt.Printf("%s\n", result)
}
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
```
#13
更多评论
buckets是个Array. key: key, doc_count, [ct], [XXX.raw]. [ ]表示可能有
xxx.raw是个Object. key: doc_count_error_upper_bound, sum_other_doc_count, buckets
aggregations是个Object. key: xxx.raw
每个都写成一个函数进行处理。前两个有相互调用的情况,但是最终buckets肯定会以没有xxx.raw项结束,不会死循环下去。
#2