elasticsearch多字段聚合實(shí)現(xiàn)方式

1聚霜、背景

我們知道在sql中是可以實(shí)現(xiàn) group by 字段a,字段b屈呕,那么這種效果在elasticsearch中該如何實(shí)現(xiàn)呢微宝?此處我們記錄在elasticsearch中的3種方式來實(shí)現(xiàn)這個(gè)效果。

2虎眨、實(shí)現(xiàn)多字段聚合的思路

實(shí)現(xiàn)多字段聚合的思路

從上圖中芥吟,我們可以知道侦铜,可以通過3種方式來實(shí)現(xiàn) 多字段的聚合操作。

3钟鸵、需求

根據(jù)省(province)和性別(sex)來進(jìn)行聚合钉稍,然后根據(jù)聚合后的每個(gè)桶的數(shù)據(jù),在根據(jù)每個(gè)桶中的最大年齡(age)來進(jìn)行倒序排序棺耍。

4贡未、數(shù)據(jù)準(zhǔn)備

4.1 創(chuàng)建索引

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"
      },
      "address": {
        "type": "text",
        "analyzer": "ik_max_word",
        "fields": {
          "keyword": {
            "type": "keyword",
            "ignore_above": 256
          }
        }
      }
    }
  }
}

4.2 準(zhǔn)備數(shù)據(jù)

PUT /_bulk
{"create":{"_index":"index_person","_id":1}}
{"id":1,"name":"張三","sex":"男","age":20,"province":"湖北","address":"湖北省黃岡市羅田縣匡河鎮(zhèn)"}
{"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":"湖北省武漢市江漢區(qū)"}
{"create":{"_index":"index_person","_id":4}}
{"id":4,"name":"趙六","sex":"女","age":30,"province":"北京","address":"北京市東城區(qū)"}
{"create":{"_index":"index_person","_id":5}}
{"id":5,"name":"錢七","sex":"女","age":16,"province":"北京","address":"北京市西城區(qū)"}
{"create":{"_index":"index_person","_id":6}}
{"id":6,"name":"王八","sex":"女","age":45,"province":"北京","address":"北京市朝陽區(qū)"}

5、實(shí)現(xiàn)方式

5.1 multi_terms實(shí)現(xiàn)

5.1.1 dsl

GET /index_person/_search
{
  "size": 0,
  "aggs": {
    "agg_province_sex": {
      "multi_terms": {
        "size": 10,
        "shard_size": 25,
        "order":{
          "max_age": "desc"    
        },
        "terms": [
          {
            "field": "province",
            "missing": "defaultProvince"
          },
          {
            "field": "sex"
          }
        ]
      },
      "aggs": {
        "max_age": {
          "max": {
            "field": "age"
          }
        }
      }
    }
  }
}

5.1.2 java 代碼

    @Test
    @DisplayName("多term聚合-根據(jù)省和性別聚合蒙袍,然后根據(jù)最大年齡倒序")
    public void agg01() throws IOException {

        SearchRequest searchRequest = new SearchRequest.Builder()
                .size(0)
                .index("index_person")
                .aggregations("agg_province_sex", agg ->
                        agg.multiTerms(multiTerms ->
                                        multiTerms.terms(term -> term.field("province"))
                                                .terms(term -> term.field("sex"))
                                                .order(new NamedValue<>("max_age", SortOrder.Desc))
                                )
                                .aggregations("max_age", ageAgg ->
                                        ageAgg.max(max -> max.field("age")))

                )
                .build();
        System.out.println(searchRequest);
        SearchResponse<Object> response = client.search(searchRequest, Object.class);
        System.out.println(response);
    }

5.1.3 運(yùn)行結(jié)果

運(yùn)行結(jié)果

5.2 script實(shí)現(xiàn)

5.2.1 dsl

GET /index_person/_search
{
  "size": 0,
  "runtime_mappings": {
    "runtime_province_sex": {
      "type": "keyword",
      "script": """
          String province = doc['province'].value;
          String sex = doc['sex'].value;
          emit(province + '|' + sex);
      """
    }
  },
  "aggs": {
    "agg_province_sex": {
      "terms": {
        "field": "runtime_province_sex",
        "size": 10,
        "shard_size": 25,
        "order": {
          "max_age": "desc"
        }
      },
      "aggs": {
        "max_age": {
          "max": {
            "field": "age"
          }
        }
      }
    }
  }
}

5.2.2 java代碼

@Test
    @DisplayName("多term聚合-根據(jù)省和性別聚合俊卤,然后根據(jù)最大年齡倒序")
    public void agg02() throws IOException {

        SearchRequest searchRequest = new SearchRequest.Builder()
                .size(0)
                .index("index_person")
                .runtimeMappings("runtime_province_sex", field -> {
                    field.type(RuntimeFieldType.Keyword);
                    field.script(script -> script.inline(new InlineScript.Builder()
                            .lang(ScriptLanguage.Painless)
                            .source("String province = doc['province'].value;\n" +
                                    "          String sex = doc['sex'].value;\n" +
                                    "          emit(province + '|' + sex);")
                            .build()));
                    return field;
                })
                .aggregations("agg_province_sex", agg ->
                        agg.terms(terms ->
                                        terms.field("runtime_province_sex")
                                                .size(10)
                                                .shardSize(25)
                                                .order(new NamedValue<>("max_age", SortOrder.Desc))
                                )
                                .aggregations("max_age", minAgg ->
                                        minAgg.max(max -> max.field("age")))
                )
                .build();
        System.out.println(searchRequest);
        SearchResponse<Object> response = client.search(searchRequest, Object.class);
        System.out.println(response);
    }

5.2.3 運(yùn)行結(jié)果

運(yùn)行結(jié)果

5.3 通過copyto實(shí)現(xiàn)

我本地測試過,通過copyto沒實(shí)現(xiàn)害幅,此處故先不考慮

5.4 通過pipeline來實(shí)現(xiàn)

實(shí)現(xiàn)思路:
創(chuàng)建mapping時(shí)消恍,多創(chuàng)建一個(gè)字段pipeline_province_sex,該字段的值由創(chuàng)建數(shù)據(jù)時(shí)指定pipeline來生產(chǎn)以现。

5.4.1 創(chuàng)建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
          }
        }
      }
    }
  }
}

此處指定了一個(gè)字段pipeline_province_sex狠怨,該字段的值會(huì)由pipeline來處理。

5.4.2 創(chuàng)建pipeline

PUT _ingest/pipeline/pipeline_index_person_provice_sex
{
  "description": "將provice和sex的值拼接起來",
  "processors": [
    {
      "set": {
        "field": "pipeline_province_sex",
        "value": ["{{province}}", "{{sex}}"]
      }, 
      "join": {
        "field": "pipeline_province_sex",
        "separator": "|"
      }
    }
  ]
}

5.4.3 插入數(shù)據(jù)

PUT /_bulk?pipeline=pipeline_index_person_provice_sex
{"create":{"_index":"index_person","_id":1}}
{"id":1,"name":"張三","sex":"男","age":20,"province":"湖北","address":"湖北省黃岡市羅田縣匡河鎮(zhèn)"}
{"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":"湖北省武漢市江漢區(qū)"}
{"create":{"_index":"index_person","_id":4}}
{"id":4,"name":"趙六","sex":"女","age":30,"province":"北京","address":"北京市東城區(qū)"}
{"create":{"_index":"index_person","_id":5}}
{"id":5,"name":"錢七","sex":"女","age":16,"province":"北京","address":"北京市西城區(qū)"}
{"create":{"_index":"index_person","_id":6}}
{"id":6,"name":"王八","sex":"女","age":45,"province":"北京","address":"北京市朝陽區(qū)"}

注意: 此處的插入需要指定上一步的pipeline
PUT /_bulk?pipeline=pipeline_index_person_provice_sex

5.4.4 聚合dsl

GET /index_person/_search
{
  "size": 0,
  "aggs": {
    "agg_province_sex": {
      "terms": {
        "field": "pipeline_province_sex",
        "size": 10,
        "shard_size": 25,
        "order": {
          "max_age": "desc"   
        }
      }, 
      "aggs": {
        "max_age": {
          "max": {
            "field": "age"
          }
        }
      }
    }
  }
}

5.4.5 運(yùn)行結(jié)果

運(yùn)行結(jié)果

6邑遏、實(shí)現(xiàn)代碼

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

7佣赖、參考文檔

  1. https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市记盒,隨后出現(xiàn)的幾起案子憎蛤,更是在濱河造成了極大的恐慌,老刑警劉巖纪吮,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俩檬,死亡現(xiàn)場離奇詭異,居然都是意外死亡碾盟,警方通過查閱死者的電腦和手機(jī)豆胸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來巷疼,“玉大人晚胡,你說我怎么就攤上這事〗姥兀” “怎么了估盘?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長骡尽。 經(jīng)常有香客問我遣妥,道長,這世上最難降的妖魔是什么攀细? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任箫踩,我火速辦了婚禮爱态,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘境钟。我一直安慰自己锦担,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布慨削。 她就那樣靜靜地躺著洞渔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缚态。 梳的紋絲不亂的頭發(fā)上磁椒,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音玫芦,去河邊找鬼浆熔。 笑死,一個(gè)胖子當(dāng)著我的面吹牛桥帆,可吹牛的內(nèi)容都是我干的医增。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼环葵,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼调窍!你這毒婦竟也來了宝冕?” 一聲冷哼從身側(cè)響起张遭,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎地梨,沒想到半個(gè)月后菊卷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宝剖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年洁闰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片万细。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡扑眉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赖钞,到底是詐尸還是另有隱情腰素,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布雪营,位于F島的核電站弓千,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏献起。R本人自食惡果不足惜洋访,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一镣陕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧姻政,春花似錦呆抑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至善镰,卻和暖如春妹萨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炫欺。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來泰國打工乎完, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人品洛。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓树姨,卻偏偏與公主長得像,于是被迫代替她去往敵國和親桥状。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帽揪,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容