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)
```
```go
package main
import (
"fmt"
"strconv"
"strings"
"github.com/tidwall/gjson"
)
func main() {
each(gjson.Parse(js), "")
}
func each(r gjson.Result, path string) {
r.ForEach(func(key, value gjson.Result) bool {
var current string
// 转义 . 字符,参考资料.
// https://github.com/tidwall/gjson#path-syntax
// 如果不需要path再次处理json,可以不用转
k := strings.Replace(key.String(), ".", `\.`, -1)
if path != "" {
current = path + "." + k
} else {
current = k
}
if value.IsObject() {
each(value, current)
} else if value.IsArray() {
for i, v := range value.Array() {
current = path + "." + strconv.Itoa(i)
each(v, current)
}
} else {
fmt.Println(current, ":", value)
}
return true
})
}
```
转换成 键值对 这样应该比较好处理了吧
```
took : 596(Number)
timed_out : false(False)
_shards.total : 11(Number)
_shards.successful : 11(Number)
_shards.failed : 0(Number)
hits.total : 1121497(Number)
hits.max_score : 0(Number)
aggregations.day\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.key : 20170418(String)
aggregations.day\.raw.0.doc_count : 1121497(Number)
aggregations.day\.raw.0.channel\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.0.key : channel01(String)
aggregations.day\.raw.0.channel\.raw.0.doc_count : 901649(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.0.key : show(String)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.0.doc_count : 424711(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.0.ct.value : 143760(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.1.key : click(String)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.1.doc_count : 253006(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.1.ct.value : 114883(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.2.key : install(String)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.2.doc_count : 139527(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.2.ct.value : 68115(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.3.key : installed(String)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.3.doc_count : 84405(Number)
aggregations.day\.raw.0.channel\.raw.0.acttype\.raw.3.ct.value : 49037(Number)
aggregations.day\.raw.0.channel\.raw.1.key : channel02(String)
aggregations.day\.raw.0.channel\.raw.1.doc_count : 107639(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.0.key : show(String)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.0.doc_count : 50364(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.0.ct.value : 17019(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.1.key : click(String)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.1.doc_count : 32334(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.1.ct.value : 14123(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.2.key : install(String)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.2.doc_count : 19891(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.2.ct.value : 9259(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.3.key : installed(String)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.3.doc_count : 5050(Number)
aggregations.day\.raw.0.channel\.raw.1.acttype\.raw.3.ct.value : 2922(Number)
aggregations.day\.raw.0.channel\.raw.2.key : channel03(String)
aggregations.day\.raw.0.channel\.raw.2.doc_count : 69671(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.0.key : show(String)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.0.doc_count : 26617(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.0.ct.value : 8229(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.1.key : click(String)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.1.doc_count : 22793(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.1.ct.value : 7812(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.2.key : install(String)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.2.doc_count : 19919(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.2.ct.value : 6165(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.3.key : installed(String)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.3.doc_count : 342(Number)
aggregations.day\.raw.0.channel\.raw.2.acttype\.raw.3.ct.value : 290(Number)
aggregations.day\.raw.0.channel\.raw.3.key : channel04(String)
aggregations.day\.raw.0.channel\.raw.3.doc_count : 42511(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.0.key : show(String)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.0.doc_count : 22565(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.0.ct.value : 8044(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.1.key : click(String)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.1.doc_count : 11601(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.1.ct.value : 5890(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.2.key : install(String)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.2.doc_count : 7208(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.2.ct.value : 3802(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.3.key : installed(String)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.3.doc_count : 1137(Number)
aggregations.day\.raw.0.channel\.raw.3.acttype\.raw.3.ct.value : 761(Number)
aggregations.day\.raw.0.channel\.raw.4.key : channel05(String)
aggregations.day\.raw.0.channel\.raw.4.doc_count : 27(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.doc_count_error_upper_bound : 0(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.sum_other_doc_count : 0(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.0.key : show(String)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.0.doc_count : 20(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.0.ct.value : 7(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.1.key : click(String)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.1.doc_count : 7(Number)
aggregations.day\.raw.0.channel\.raw.4.acttype\.raw.1.ct.value : 2(Number)
```
#31
更多评论
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