ES的cardinality去重问题以及桶聚合详细使用
2024-12-18 10:31:52 # 问题总结 # elasticsearch # ES去重方式--桶聚合

ES的cardinality去重问题以及桶聚合详细使用

cardinality介绍

cardinality是一个近似算法,是基于HLL算法进行计算的,HLL算法会先对我们的输入进行哈希计算,然后根据哈希计算结果中的bits做概率估算得到基数

优点是:性能快,上亿的数据可以一秒完成

缺点是:只能保证40000条的数据,超过这个数据量就会产生5%的偏差,不适合精准去重

示例

下面这个例子是在服务器上运行的cardinality进行去重的语句

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
curl -X GET "http://elastic:es123@data1:9200/dwd_sc_repaircontract_jzfx/_search" -H 'Content-Type: application/json' -d '{
"size": 0,
"query": {
"bool": {
"must": [
{
"term": {
"brand": "奇瑞"
}
},
{
"term": {
"invoiceyear": "2023"
}
},
{
"term": {
"car_series_code": "T19C"
}
},
{
"range": {
"arrivetime": {
"gte": "2024-01-01",
"lte": "2024-12-31"
}
}
}
]
}
},
"aggs": {
"unique_vin": {
"cardinality": {
"field": "vin",
"precision_threshold": 400000
}
}
}
}'

最后我们得到的结果是4716

实际上我们去重之后的结果应该是4117,产生了一条数据精度不准的情况,那么我们应该怎么避免这种情况呢

stats_bucket方式实现去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
GET /dwd_sc_repaircontract_jzfx/_search
{
"size": 0,
"query": {
"bool": {
"must": [
{ "term": { "invoiceyear": "2023" } },
{ "term": { "car_series_code": "T19C" } },
{
"range": {
"arrivetime": {
"gte": "2023-01-01",
"lte": "2023-12-31"
}
}
}
]
}
},
"aggs": {
"unique_vins": {
"terms": {
"field": "vin",
"size": 50000
}
},
"total_unique_vin_count": {
"stats_bucket": {
"buckets_path": "unique_vins._count"
}
}
}
}

"aggs"部分定义了聚合操作,用于对查询得到的数据进行统计分析。本例中包含了两个聚合操作:

"unique_vins": { "terms": { "field": "vin", "size": 50000 } }:这是一个 terms 聚合,用于统计符合条件的数据中不同 vin(车辆识别码)的数量。size: 50000 表示最多返回50000个不同的 vin 值。这里是为了获取符合条件的车辆的不同 vin 列表。

"total_unique_vin_count": { "stats_bucket": { "buckets_path": "unique_vins._count" } }:这是一个 stats_bucket 聚合,目的是对 “unique_vins” 聚合的桶进行统计,获取符合条件的不同 vin 数量的统计数据(例如总数、平均值等)。

"buckets_path": "unique_vins._count" 表示从 unique_vins 聚合桶中获取各 vin 出现的次数。