elasticsearch bucket 之rare terms聚合

2022-11-23 06:00:54

1、背景

我們知道當我們使用 terms聚合時,當修改預設順序為_count asc時,統計的結果是不準備的,而且官方也不推薦我們這樣做,而是推薦使用rare terms聚合。rare terms是一個稀少的term聚合,可以一定程度的解決升序問題。

2、需求

統計province欄位中包含上和湖的term資料,並且最多隻能出現2次。獲取到聚合後的結果。

3、前置準備

3.1 準備mapping

PUT /index_person
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "id": {
        "type": "long"
      },
      "name": {
        "type": "keyword"
      },
      "province": {
        "type": "keyword"
      },
      "sex": {
        "type": "keyword"
      },
      "age": {
        "type": "integer"
      },
      "pipeline_province_sex":{
        "type": "keyword"
      },
      "address": {
        "type": "text",
        "analyzer": "ik_max_word",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

3.2 準備資料


PUT /_bulk
{"create":{"_index":"index_person","_id":1}}
{"id":1,"name":"張三","sex":"男","age":20,"province":"湖北","address":"湖北省黃岡市羅田縣匡河鎮"}
{"create":{"_index":"index_person","_id":2}}
{"id":2,"name":"李四","sex":"男","age":19,"province":"江蘇","address":"江蘇省南京市"}
{"create":{"_index":"index_person","_id":3}}
{"id":3,"name":"王武","sex":"女","age":25,"province":"湖北","address":"湖北省武漢市江漢區"}
{"create":{"_index":"index_person","_id":4}}
{"id":4,"name":"趙六","sex":"女","age":30,"province":"北京","address":"北京市東城區"}
{"create":{"_index":"index_person","_id":5}}
{"id":5,"name":"錢七","sex":"女","age":16,"province":"北京","address":"北京市西城區"}
{"create":{"_index":"index_person","_id":6}}
{"id":6,"name":"王八","sex":"女","age":45,"province":"北京","address":"北京市朝陽區"}
{"create":{"_index":"index_person","_id":7}}
{"id":7,"name":"九哥","sex":"男","age":25,"province":"上海市","address":"上海市嘉定區"}

4、實現需求

4.1 dsl

GET /index_person/_search
{
  "size": 0,
  "aggs": {
    "agg_province": {
      "rare_terms": {
        "field": "province",
        "max_doc_count": 2,
        "precision": 0.01,
        "include": "(.*上.*|.*湖.*|.*江.*)",
        "exclude": ["江蘇"],
        "missing": "default省"
      }
    }
  }
}

4.2 java程式碼

@Test
@DisplayName("稀少的term聚合,類似按照 _count asc 排序的terms聚合,但是terms聚合中按照_count asc的結果是不準的,需要使用 rare terms 聚合")
public void agg01() throws IOException {

    SearchRequest searchRequest = new SearchRequest.Builder()
            .size(0)
            .index("index_person")
            .aggregations("agg_province", agg ->
                    agg.rareTerms(rare ->
                            // 稀有詞 的欄位
                            rare.field("province")
                                    // 該稀有詞最多可以出現在幾個檔案中,最大值為100,如果要調整,需要修改search.max_buckets引數的值(嘗試修改這個值,不生效)
                                    // 在該例子中,只要是出現的次數<=2的聚合都會返回
                                    .maxDocCount(2L)
                                    // 內部布穀鳥過濾器的精度,精度越小越準,但是相應的消耗記憶體也越多,最小值為 0.00001,預設值為 0.01
                                    .precision(0.01)
                                    // 應該包含在聚合的term, 當是單個欄位是,可以寫正規表示式
                                    .include(include -> include.regexp("(.*上.*|.*湖.*|.*江.*)"))
                                    // 排出在聚合中的term,當是集合時,需要寫準確的值
                                    .exclude(exclude -> exclude.terms(Collections.singletonList("江蘇")))
                                    // 當檔案中缺失province欄位時,給預設值
                                    .missing("default省")
                    )
            )
            .build();
    System.out.println(searchRequest);
    SearchResponse<Object> response = client.search(searchRequest, Object.class);
    System.out.println(response);
}

一些注意事項都在註釋中。

4.3 執行結果

5、max_doc_count 和 search.max_buckets

6、注意事項

  1. rare terms統計返回的資料沒有大小限制,而且受max_doc_count引數的限制,比如:如果複合 max_doc_count 的分組有60個,那麼這60個分組會直接返回。
  2. max_doc_count的值最大為100,貌似不能修改。
  3. 如果一臺節點聚合收集的結果過多,那麼很容易超過 search.max_buckets的值,此時就需要修改這個值。
# 臨時修改
PUT /_cluster/settings
{"transient": {"search.max_buckets": 65536}}

# 永久修改
PUT /_cluster/settings
{"persistent": {"search.max_buckets": 65536}}

7、完整程式碼

https://gitee.com/huan1993/spring-cloud-parent/blob/master/es/es8-api/src/main/java/com/huan/es8/aggregations/bucket/RareTermsAggs.java

8、參考檔案

  1. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-rare-terms-aggregation.html