adjacency matrix aggregation
邻接矩阵聚合
定义
对某个字段的值做矩阵,返回单独满足一个/同时满足两个的结果
A | B | C | |
---|---|---|---|
A | A | A&B | A&C |
B | B | B&C | |
C | C |
测试:
环境准备
- 初始化一个带
Kibana
的ES
集群- 参考 环境搭建攻略
- 本文使用的是
ES 7.16
,与上文中的集群版本不一致
- 在首页中添加示例数据
add sample data
测试执行
分别执行以下命令,可以得到以下结果
POST kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"adjacency": {
"adjacency_matrix": {
"filters": {
"O": {
"terms": {
"manufacturer.keyword": [
"Oceanavigations"
]
}
},
"E": {
"terms": {
"manufacturer.keyword": [
"Elitelligence"
]
}
},
"L": {
"terms": {
"manufacturer.keyword": [
"Low Tide Media"
]
}
}
}
}
}
}
}
{
"took" : 37,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"adjacency" : {
"buckets" : [
{
"key" : "E",
"doc_count" : 142214
},
{
"key" : "E&L",
"doc_count" : 61374
},
{
"key" : "E&O",
"doc_count" : 31007
},
{
"key" : "L",
"doc_count" : 161024
},
{
"key" : "L&O",
"doc_count" : 34019
},
{
"key" : "O",
"doc_count" : 126266
}
]
}
}
}
POST kibana_sample_data_ecommerce/_search
{
"size": 0,
"aggs": {
"adjacency": {
"adjacency_matrix": {
"filters": {
"O": {
"match":{
"customer_gender":"FEMALE"
}
},
"E": {
"match":{
"customer_gender":"MALE"
}
}
}
}
}
}
}
{
"took" : 85,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 10000,
"relation" : "gte"
},
"max_score" : null,
"hits" : [ ]
},
"aggregations" : {
"adjacency" : {
"buckets" : [
{
"key" : "E",
"doc_count" : 232447
},
{
"key" : "O",
"doc_count" : 252530
}
]
}
}
}
总结与注意点
邻接矩阵的聚合是作用在同一字段中不同值的交叉对比和聚合(对ES
来说,所有的字段都可以存为数组),所以可以看到结果集会像文章最开头的矩阵一样存在单一标签、组合标签的聚合结果的展示。
filters
的部分是必填的,但是里面填的内容和普通dsl
一样,主要是为了给当前这部分数据进行分组- 分组之后的结果默认用
&
相连,需要自己进行和结果矩阵构建 - 如果标签之间不存在
overlap
的结果,返回的结果就和普通的terms
一样了
使用场景
官方建议是配合date_histogram
做dynamic network analysis
这里我们可以考虑做的是:
- 用户/特征分组,如:年纪在
20~25
岁的用户,在北京
或上海
的用户有多少 - 问题归因,如:同属于
groupA
、groupB
…的服务器有多少
个人理解这个聚合和普通的 terms
的差异在于,某些标签可能为了方便存储和召回会直接以数组方式存储,如果单纯的以 terms
做聚合就会丧失同一条数据多种不同标签的关联关系
FAQ
- Q:官方示例里为啥用
terms
处理两个标签?- A:这个聚合的根本思想是看几个包含
1..N
个标签的组中,每个标签去和其他组做join
,看他们俩俩之间的交集有多少
- A:这个聚合的根本思想是看几个包含