此處將單記錄一下 global
、 filters
和cardinality
的聚合操作。
global
聚合是全域性聚合,是對所有的檔案進行聚合,而不受查詢條件的限制。
global
聚合器只能作為頂級聚合器
,因為將一個 global 聚合器嵌入另一個桶聚合器是沒有意義的。
比如: 我們有50個檔案,通過查詢條件篩選之後存在10個檔案,此時我想統計總共有多少個檔案。是50個,因為global
統計不受查詢條件的限制。
定義一個多桶聚合,其中每個桶都與一個過濾器相關聯。每個桶都會收集與其關聯的過濾器匹配的所有檔案。
比如: 我們總共有50個檔案,通過查詢條件篩選之後存在10個檔案,此時我想統計 這10個檔案中,出現info
詞語的檔案有多少個,出現warn
詞語的檔案有多少個。
類似於 SQL
中的 COUNT(DISTINCT(欄位))
,不過這個是近似統計,是基於 HyperLogLog++
來實現的。
我們有一組紀錄檔
,每條紀錄檔都存在id
和message
2個欄位。此時根據message
欄位過濾出存在info warn
的紀錄檔,然後進行統計:
global + cardinality
)filters
)PUT /index_api_log
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"message":{
"type": "text"
},
"id": {
"type": "long"
}
}
}
}
PUT /index_api_log/_bulk
{"index":{"_id":1}}
{"message": "this is info message-01","id":1}
{"index":{"_id":2}}
{"message": "this is info message-02","id":2}
{"index":{"_id":3}}
{"message": "this is warn message-01","id":3}
{"index":{"_id":4}}
{"message": "this is error message","id":4}
{"index":{"_id":5}}
{"message": "this is info and warn message","id":5}
POST /index_api_log/_search
{
"size": 0,
"query": {
"bool": {
"must": [
{
"match": {
"message": "info warn"
}
}
]
}
},
"aggregations": {
"agg_01": {
"filters": {
"filters": {
"info": {
"match": {
"message": "info"
}
},
"warn": {
"match": {
"message": "warn"
}
}
},
"other_bucket": true,
"other_bucket_key": "other"
}
},
"agg_02":{
"global": {},
"aggs": {
"total": {
"cardinality": {
"field": "id",
"precision_threshold": 30000
}
}
}
}
}
}
@Test
@DisplayName("global and filters and cardinality 聚合")
public void test01() throws IOException {
SearchRequest request = SearchRequest.of(searchRequest ->
searchRequest.index("index_api_log")
// 查詢 message 中存在 info 和 warn 的紀錄檔
.query(query -> query.bool(bool -> bool.must(must -> must.match(match -> match.field("message").query("info warn")))))
// 查詢的結果不返回
.size(0)
// 第一個聚合
.aggregations("agg_01", agg ->
agg.filters(filters ->
filters.filters(f ->
f.array(
Arrays.asList(
// 在上一步query的結果中,將 message中包含info的進行聚合
Query.of(q -> q.match(m -> m.field("message").query("info"))),
// 在上一步query的結果中,將 message中包含warn的進行聚合
Query.of(q -> q.match(m -> m.field("message").query("warn")))
)
)
)
// 如果上一步的查詢中,存在非 info 和 warn的則是否聚合到 other 桶中
.otherBucket(true)
// 給 other 桶取一個名字
.otherBucketKey("other")
)
)
// 第二個聚合
.aggregations("agg_02", agg ->
agg
// 此處的 global 聚合只能放在頂部
.global(global -> global)
// 子聚合,資料來源於所有的檔案,不受上一步query結果的限制
.aggregations("total", subAgg ->
// 類似於SQL中的 count(distinct(欄位)),是一個近似統計
subAgg.cardinality(cardinality ->
// 統計的欄位
cardinality.field("id")
// 精度,預設值是30000,最大值也是40000,不超過這個值的聚合近似準確值
.precisionThreshold(30000)
)
)
)
);
System.out.println("request: " + request);
SearchResponse<String> response = client.search(request, String.class);
System.out.println("response: " + response);
}
本文來自部落格園,作者:huan1993,轉載請註明原文連結:https://www.cnblogs.com/huan1993/p/16971329.html