日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

文檔

統計聚合

更新時間:

使用統計聚合功能可以實現求最小值、求最大值、求和、求平均值、統計行數、去重統計行數、百分位統計、按字段值分組、按范圍分組、按地理位置分組、按過濾條件分組、直方圖統計、日期直方圖統計、獲取統計聚合分組內的行、嵌套查詢等;同時多個統計聚合功能可以組合使用,滿足復雜的查詢需求。

流程

統計聚合的完整執行流程如下圖所示。

fig_agg_pro

統計聚合是在服務端的“查詢”結束后執行,服務端會將“查詢”階段命中的所有文檔根據查詢請求進行統計聚合,因此統計聚合請求相比沒有統計聚合的請求會復雜。

背景信息

統計聚合的詳細功能請參見下表。

功能

說明

最小值

返回一個字段中的最小值,類似于SQL中的min。

最大值

返回一個字段中的最大值,類似于SQL中的max。

返回數值字段的總數,類似于SQL中的sum。

平均值

返回數值字段的平均值,類似于SQL中的avg。

統計行數

返回指定字段值的數量或者多元索引數據總行數,類似于SQL中的count。

去重統計行數

返回指定字段不同值的數量,類似于SQL中的count(distinct)。

百分位統計

百分位統計常用來統計一組數據的百分位分布情況,例如在日常系統運維中統計每次請求訪問的耗時情況時,需要關注系統請求耗時的P25、P50、P90、P99值等分布情況。

字段值分組

根據一個字段的值對查詢結果進行分組,相同的字段值放到同一分組內,返回每個分組的值和該值對應的個數。

說明

當分組較大時,按字段值分組可能會存在誤差。

多字段分組

根據多個字段對查詢結果進行分組,支持使用token進行翻頁。

范圍分組

根據一個字段的范圍對查詢結果進行分組,字段值在某范圍內放到同一分組內,返回每個范圍中相應的item個數。

地理位置分組

根據距離某一個中心點的范圍對查詢結果進行分組,距離差值在某范圍內放到同一分組內,返回每個范圍中相應的item個數。

過濾條件分組

按照過濾條件對查詢結果進行分組,獲取每個過濾條件匹配到的數量,返回結果的順序和添加過濾條件的順序一致。

直方圖統計

按照指定數據間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數。

日期直方圖統計

對日期字段類型的數據按照指定間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數。

獲取統計聚合分組中的行

對查詢結果進行分組后,獲取每個分組內的一些行數據,可實現和MySQL中ANY_VALUE(field)類似的功能。

嵌套

分組類型的統計聚合功能支持嵌套,其內部可以添加子統計聚合。

多個統計聚合

多個統計聚合功能可以組合使用。

說明

當多個統計聚合的復雜度較高時可能會影響響應速度。

前提條件

最小值

返回一個字段中的最小值,類似于SQL中的min。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double和Date類型。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 商品庫中有每一種商品的價格,求產地為浙江省的商品中,價格最低的商品價格是多少。
     * 等效的SQL語句是SELECT min(column_price) FROM product where place_of_production="浙江省"。
     */
    public void min(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.term("place_of_production", "浙江省"))
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.min("min_agg_1", "column_price").missing(100))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsMinAggregationResult("min_agg_1").getValue());
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            TermQuery query = new TermQuery();
            query.setTerm(ColumnValue.fromString("浙江省"));
            query.setFieldName("place_of_production");
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.term("place_of_production", "浙江省").build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            MinAggregation aggregation = new MinAggregation();
            aggregation.setAggName("min_agg_1");
            aggregation.setFieldName("column_price");
            aggregation.setMissing(ColumnValue.fromLong(100));
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // MinAggregation aggregation2 = AggregationBuilders.min("min_agg_1", "column_price").missing(100).build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsMinAggregationResult("min_agg_1").getValue());
        }
    }

最大值

返回一個字段中的最大值,類似于SQL中的max。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double和Date類型。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 商品庫中有每一種商品的價格,求產地為浙江省的商品中,價格最高的商品價格是多少。
     * 等效的SQL語句是SELECT max(column_price) FROM product where place_of_production="浙江省"。
     */
    public void max(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.term("place_of_production", "浙江省"))
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.max("max_agg_1", "column_price").missing(0))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsMaxAggregationResult("max_agg_1").getValue());
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            TermQuery query = new TermQuery();
            query.setTerm(ColumnValue.fromString("浙江省"));
            query.setFieldName("place_of_production");
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.term("place_of_production", "浙江省").build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            MaxAggregation aggregation = new MaxAggregation();
            aggregation.setAggName("max_agg_1");
            aggregation.setFieldName("column_price");
            aggregation.setMissing(ColumnValue.fromLong(100));
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // MaxAggregation aggregation2 = AggregationBuilders.max("max_agg_1", "column_price").missing(100).build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsMaxAggregationResult("max_agg_1").getValue());
        }
    }

返回數值字段的總數,類似于SQL中的sum。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long和Double類型。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 商品庫中有每一種商品的價格,求產地為浙江省的商品中,價格最高的商品價格是多少。
     * 等效的SQL語句是SELECT sum(column_price) FROM product where place_of_production="浙江省"。
     */
    public void sum(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.term("place_of_production", "浙江省"))
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.sum("sum_agg_1", "column_number").missing(10))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsSumAggregationResult("sum_agg_1").getValue());
        }
    
        // 使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            TermQuery query = new TermQuery();
            query.setTerm(ColumnValue.fromString("浙江省"));
            query.setFieldName("place_of_production");
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.term("place_of_production", "浙江省").build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            SumAggregation aggregation = new SumAggregation();
            aggregation.setAggName("sum_agg_1");
            aggregation.setFieldName("column_number");
            aggregation.setMissing(ColumnValue.fromLong(100));
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // SumAggregation aggregation2 = AggregationBuilders.sum("sum_agg_1", "column_number").missing(10).build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsSumAggregationResult("sum_agg_1").getValue());
        }
    }

平均值

返回數值字段的平均值,類似于SQL中的avg。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double和Date類型。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 商品庫中有每一種商品的售出數量,求產地為浙江省的商品中,平均價格是多少。
     * 等效的SQL語句是SELECT avg(column_price) FROM product where place_of_production="浙江省"。
     */
    public void avg(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.term("place_of_production", "浙江省"))
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.avg("avg_agg_1", "column_price"))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsAvgAggregationResult("avg_agg_1").getValue());
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            TermQuery query = new TermQuery();
            query.setTerm(ColumnValue.fromString("浙江省"));
            query.setFieldName("place_of_production");
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.term("place_of_production", "浙江省").build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            AvgAggregation aggregation = new AvgAggregation();
            aggregation.setAggName("avg_agg_1");
            aggregation.setFieldName("column_price");
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // AvgAggregation aggregation2 = AggregationBuilders.avg("avg_agg_1", "column_price").build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsAvgAggregationResult("avg_agg_1").getValue());
        }
    }
                        

統計行數

返回指定字段值的數量或者多元索引數據總行數,類似于SQL中的count。

說明

通過如下方式可以統計多元索引數據總行數或者某個query匹配的行數。

  • 使用統計聚合的count功能,在請求中設置count(*)。

  • 使用query功能的匹配行數,在query中設置setGetTotalCount(true);如果需要統計多元索引數據總行數,則使用MatchAllQuery。

如果需要獲取多元索引數據某列出現的次數,則使用count(列名),可應用于稀疏列的場景。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double、Boolean、Keyword、Geo_point和Date類型。

  • 示例

    /**
     * 商家庫中有每一種商家的懲罰記錄,求浙江省的商家中,有懲罰記錄的一共有多少個商家。如果商家沒有懲罰記錄,則商家信息中不存在該字段。
     * 等效的SQL語句是SELECT count(column_history) FROM product where place_of_production="浙江省"。
     */
    public void count(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.term("place_of_production", "浙江省"))
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.count("count_agg_1", "column_history"))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsCountAggregationResult("count_agg_1").getValue());
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            TermQuery query = new TermQuery();
            query.setTerm(ColumnValue.fromString("浙江省"));
            query.setFieldName("place_of_production");
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.term("place_of_production", "浙江省").build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            CountAggregation aggregation = new CountAggregation();
            aggregation.setAggName("count_agg_1");
            aggregation.setFieldName("column_history");
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // CountAggregation aggregation2 = AggregationBuilders.count("count_agg_1", "column_history").build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsCountAggregationResult("count_agg_1").getValue());
        }
    }

去重統計行數

返回指定字段不同值的數量,類似于SQL中的count(distinct)。

說明

去重統計行數的計算結果是個近似值。

  • 當去重統計行數小于1萬時,計算結果接近精確值。

  • 當去重統計行數達到1億時,計算結果的誤差為2%左右。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double、Boolean、Keyword、Geo_point和Date類型。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 求所有商品的產地一共來自多少個省份。
     * 等效的SQL語句是SELECT count(distinct column_place) FROM product。
     */
    public void distinctCount(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("<SEARCH_INDEX_NAME>")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.matchAll())
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.distinctCount("dis_count_agg_1", "column_place"))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("dis_count_agg_1").getValue());
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            MatchAllQuery query = new MatchAllQuery();
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.matchAll().build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            DistinctCountAggregation aggregation = new DistinctCountAggregation();
            aggregation.setAggName("dis_count_agg_1");
            aggregation.setFieldName("column_place");
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // DistinctCountAggregation aggregation2 = AggregationBuilders.distinctCount("dis_count_agg_1", "column_place").build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("dis_count_agg_1").getValue());
        }
    }

百分位統計

百分位統計常用來統計一組數據的百分位分布情況,例如在日常系統運維中統計每次請求訪問的耗時情況時,需要關注系統請求耗時的P25、P50、P90、P99值等分布情況。

說明

百分位統計為非精確統計,對不同百分位數值的計算精確度不同,較為極端的百分位數值更加準確,例如1%或99%的百分位數值會比50%的百分位數值準確。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double和Date類型。

    percentiles

    百分位分布例如50、90、99,可根據需要設置一個或者多個百分位。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 分析系統請求耗時百分位數分布情況。
     */
    public void percentilesAgg(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("indexName")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.matchAll())
                                    .limit(0) //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addAggregation(AggregationBuilders.percentiles("percentilesAgg", "latency")
                                            .percentiles(Arrays.asList(25.0d, 50.0d, 99.0d))
                                            .missing(1.0))
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取結果。
            PercentilesAggregationResult percentilesAggregationResult = resp.getAggregationResults().getAsPercentilesAggregationResult("percentilesAgg");
            for (PercentilesAggregationItem item : percentilesAggregationResult.getPercentilesAggregationItems()) {
                System.out.println("key:" + item.getKey() + " value:" + item.getValue().asDouble());
            }
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            MatchAllQuery query = new MatchAllQuery();
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.matchAll().build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            PercentilesAggregation aggregation = new PercentilesAggregation();
            aggregation.setAggName("percentilesAgg");
            aggregation.setFieldName("latency");
            aggregation.setPercentiles(Arrays.asList(25.0d, 50.0d, 99.0d));
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // AggregationBuilders.percentiles("percentilesAgg", "latency").percentiles(Arrays.asList(25.0d, 50.0d, 99.0d)).missing(1.0).build();
            List<Aggregation> aggregationList = new ArrayList<Aggregation>();
            aggregationList.add(aggregation);
            searchQuery.setAggregationList(aggregationList);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取結果。
            PercentilesAggregationResult percentilesAggregationResult = resp.getAggregationResults().getAsPercentilesAggregationResult("percentilesAgg");
            for (PercentilesAggregationItem item : percentilesAggregationResult.getPercentilesAggregationItems()) {
                System.out.println("key:" + item.getKey() + " value:" + item.getValue().asDouble());
            }
        }
    }

字段值分組

根據一個字段的值對查詢結果進行分組,相同的字段值放到同一分組內,返回每個分組的值和該值對應的個數。

說明
  • 當分組較大時,按字段值分組可能會存在誤差。

  • 要實現多字段分組,您可以通過字段分組嵌套或者多字段分組方式實現。關于兩種實現方式的功能對比,請參見附錄:多字段分組不同實現方式對比

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long、Double、Boolean、Keyword和Date類型。

    groupBySorter

    分組中的item排序規則,默認按照分組中item的數量降序排序,多個排序則按照添加的順序進行排列。支持的排序類型如下。

    • 按照值的字典序升序排列

    • 按照值的字典序降序排列

    • 按照行數升序排列

    • 按照行數降序排列

    • 按照子統計聚合結果中值升序排列

    • 按照子統計聚合結果中值降序排列

    size

    返回的分組數量,默認值為10。最大值為2000。當分組數量超過2000時,只會返回前2000個分組。

    subAggregation和subGroupBy

    子統計聚合,子統計聚合會根據分組內容再進行一次統計聚合分析。

    • 場景

      統計每個類別的商品數量,且統計每個類別價格的最大值和最小值。

    • 方法

      最外層的統計聚合是根據類別進行分組,再添加兩個子統計聚合求價格的最大值和最小值。

    • 結果示例

      • 水果:5個(其中價格的最大值為15,最小值為3)

      • 洗漱用品:10個(其中價格的最大值為98,最小值為1)

      • 電子設備:3個(其中價格的最大值為8699,最小值為2300)

      • 其它:15個(其中價格的最大值為1000,最小值為80)

  • 示例

    按單字段分組

    /**
     * 所有商品中每一個類別各有多少個,且統計每一個類別的價格最大值和最小值。
     * 返回結果舉例:"水果:5個(其中價格的最大值為15,最小值為3),洗漱用品:10個(其中價格的最大值為98,最小值為1),電子設備:3個(其中價格的最大值為8699,最小值為2300),
     * 其它:15個(其中價格的最大值為1000,最小值為80)"。
     */
    public void groupByField(SyncClient client) {
        //使用builder模式構建查詢語句。
        {
            SearchRequest searchRequest = SearchRequest.newBuilder()
                    .tableName("<TABLE_NAME>")
                    .indexName("indexName")
                    .searchQuery(
                            SearchQuery.newBuilder()
                                    .query(QueryBuilders.matchAll())
                                    .limit(0)  //如果只關心統計聚合結果,不關心具體數據,您可以將limit設置為0來提高性能。
                                    .addGroupBy(GroupByBuilders
                                            .groupByField("name1", "column_type")
                                            .addSubAggregation(AggregationBuilders.min("subName1", "column_price"))
                                            .addSubAggregation(AggregationBuilders.max("subName2", "column_price"))
                                    )
                                    .build())
                    .build();
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name1").getGroupByFieldResultItems()) {
                //打印值。
                System.out.println(item.getKey());
                //打印個數。
                System.out.println(item.getRowCount());
                //打印價格的最小值。
                System.out.println(item.getSubAggregationResults().getAsMinAggregationResult("subName1").getValue());
                //打印價格的最大值。
                System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName2").getValue());
            }
        }
    
        //使用非builder模式構建查詢語句。
        {
            SearchRequest searchRequest = new SearchRequest();
            searchRequest.setTableName("<TABLE_NAME>");
            searchRequest.setIndexName("<SEARCH_INDEX_NAME>");
    
            SearchQuery searchQuery = new SearchQuery();
            MatchAllQuery query = new MatchAllQuery();
            //下述注釋的builder寫法等效于上述TermQuery構建寫法。
            // Query query2 = QueryBuilders.matchAll().build();
    
            searchQuery.setQuery(query);
            searchQuery.setLimit(0);
    
            GroupByField groupByField = new GroupByField();
            groupByField.setGroupByName("name1");
            groupByField.setFieldName("column_type");
            //設置子統計聚合。
            MinAggregation minAggregation = AggregationBuilders.min("subName1", "column_price").build();
            MaxAggregation maxAggregation = AggregationBuilders.max("subName2", "column_price").build();
            groupByField.setSubAggregations(Arrays.asList(minAggregation, maxAggregation));
    
            //下述注釋的builder寫法等效于上述aggregation構建寫法。
            // GroupByBuilders.groupByField("name1", "column_type")
            //        .addSubAggregation(AggregationBuilders.min("subName1", "column_price"))
            //        .addSubAggregation(AggregationBuilders.max("subName2", "column_price").build());
            List<GroupBy> groupByList = new ArrayList<GroupBy>();
            groupByList.add(groupByField);
            searchQuery.setGroupByList(groupByList);
            searchRequest.setSearchQuery(searchQuery);
    
            //執行查詢。
            SearchResponse resp = client.search(searchRequest);
            //獲取統計聚合結果。
            for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name1").getGroupByFieldResultItems()) {
                //打印值。
                System.out.println(item.getKey());
                //打印個數。
                System.out.println(item.getRowCount());
                //打印價格的最小值。
                System.out.println(item.getSubAggregationResults().getAsMinAggregationResult("subName1").getValue());
                //打印價格的最大值。
                System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName2").getValue());
            }
        }
    }

    通過字段分組嵌套進行多字段分組

    /**
     * 按照嵌套多字段分組的示例。
     * 多元索引支持通過嵌套使用兩個groupBy實現與SQL中的groupBy多字段相似的功能。
     * 等效的SQL語句是select a,d, sum(b),sum(c) from user group by a,d。
     */
    public void GroupByMultiField() {
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .returnAllColumns(true)   //設置為false時,指定addColumnsToGet,性能會高。
            //.addColumnsToGet("col_1","col_2")
            .searchQuery(SearchQuery.newBuilder()
                .query(QueryBuilders.matchAll())   //此處相當于SQL中的where條件,可以通過QueryBuilders.bool()嵌套查詢實現復雜的查詢。
                .addGroupBy(
                    GroupByBuilders
                        .groupByField("任意唯一名字標識_1", "field_a")
                        .size(20)
                        .addSubGroupBy(
                            GroupByBuilders
                                .groupByField("任意唯一名字標識_2", "field_d")
                                .size(20)
                                .addSubAggregation(AggregationBuilders.sum("任意唯一名字標識_3", "field_b"))
                                .addSubAggregation(AggregationBuilders.sum("任意唯一名字標識_4", "field_c"))
                        )
                )
                .build())
            .build();
        SearchResponse response = client.search(searchRequest);
        //查詢符合條件的行。
        List<Row> rows = response.getRows();
        //獲取統計聚合結果。
        GroupByFieldResult groupByFieldResult1 = response.getGroupByResults().getAsGroupByFieldResult("任意唯一名字標識_1");
        for (GroupByFieldResultItem resultItem : groupByFieldResult1.getGroupByFieldResultItems()) {
            System.out.println("field_a key:" + resultItem.getKey() + " Count:" + resultItem.getRowCount());
            //獲取子統計聚合結果。
            GroupByFieldResult subGroupByResult = resultItem.getSubGroupByResults().getAsGroupByFieldResult("任意唯一名字標識_2");
            for (GroupByFieldResultItem item : subGroupByResult.getGroupByFieldResultItems()) {
                System.out.println("field_a " + resultItem.getKey() + " field_d key:" + item.getKey() + " Count:" + item.getRowCount());
                double sumOf_field_b = item.getSubAggregationResults().getAsSumAggregationResult("任意唯一名字標識_3").getValue();
                double sumOf_field_c = item.getSubAggregationResults().getAsSumAggregationResult("任意唯一名字標識_4").getValue();
                System.out.println("sumOf_field_b:" + sumOf_field_b);
                System.out.println("sumOf_field_c:" + sumOf_field_c);
            }
        }
    }

    按字段分組時使用統計聚合排序

    /**
     * 使用統計聚合排序的示例。
     * 使用方法:按順序添加GroupBySorter即可,添加多個GroupBySorter時排序結果按照添加順序生效。GroupBySorter支持升序和降序兩種方式。
     * 默認排序是按照行數降序排列即GroupBySorter.rowCountSortInDesc()。
     */
    public void groupByFieldWithSort(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .searchQuery(
                SearchQuery.newBuilder()
                    .query(QueryBuilders.matchAll())
                    .limit(0)
                    .addGroupBy(GroupByBuilders
                        .groupByField("name1", "column_type")
                        //.addGroupBySorter(GroupBySorter.subAggSortInAsc("subName1")) //按照子統計聚合結果中的值升序排序。
                        .addGroupBySorter(GroupBySorter.groupKeySortInAsc())           //按照統計聚合結果中的值升序排序。
                        //.addGroupBySorter(GroupBySorter.rowCountSortInDesc())        //按照統計聚合結果中的行數降序排序。
                        .size(20)
                        .addSubAggregation(AggregationBuilders.min("subName1", "column_price"))
                        .addSubAggregation(AggregationBuilders.max("subName2", "column_price"))
                    )
                    .build())
            .build();
        //執行查詢。
        SearchResponse resp = client.search(searchRequest);
    }

多字段分組

根據多個字段對查詢結果進行分組,支持使用token進行翻頁。

說明

要實現多字段分組,您可以通過字段分組嵌套或者多字段分組方式實現。關于兩種實現方式的功能對比,請參見附錄:多字段分組不同實現方式對比

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    sources

    多列分組聚合字段對象,最多支持設置32列。支持的分組類型如下:

    重要
    • sources內分組類型的groupBySorter僅支持groupKeySort,不支持subAggSort和rowCountSort。

    • 默認降序排序。

    • 當某一列字段值不存在時,系統會返回NULL。

    • 字段值分組GroupByField:僅支持設置groupByName、fieldName和groupBySorter參數。

    • 直方圖統計GroupByHistogram:僅支持設置groupByName、fieldName、interval和groupBySorter參數

    • 日期直方圖統計GroupByDateHistogram:僅支持設置groupByName、fieldName、interval、timeZone和groupBySorter參數。

    nextToken

    進行翻頁時用于繼續獲取分組的token值。多列的字段值分組請求結果GroupByCompositeResult中會返回nextToken值,通過nextToken可翻頁獲取全量分組結果。

    size

    返回分組的數量。當滿足條件的分組數量超過size限制時,您可以通過nextToken繼續翻頁獲取分組。

    重要

    當要限制返回的分組數量時,不支持同時配置size和suggestedSize參數。一般情況下只需配置size參數即可。

    如果是用于對接例如Spark、Presto等計算引擎的高吞吐場景,則只需配置suggestedSize參數。

    suggestedSize

    可設置為大于服務端最大限制的值或-1, 服務端按實際能力返回實際行數。適用于對接例如Spark、Presto等計算引擎的高吞吐場景。

    當該值超過服務端最大值限制后會被修正為最大值。實際返回的分組結果數量為min(suggestedSize, 服務端分組數量限制,總分組數量)

    subAggregation和subGroupBy

    子統計聚合,子統計聚合會根據分組內容再進行一次統計聚合分析。

    重要

    GroupByComposite不支持作為subGroupBy。

  • 示例

    /**
     * 組合類型分組聚合:根據傳入的多個SourceGroupBy(支持groupbyField、groupByHistogram和groupByDataHistogram)進行分組聚合
     * 多列的聚合返回結果以扁平化結構返回。
     */
    public static void groupByComposite(SyncClient client) {
        GroupByComposite.Builder compositeBuilder = GroupByBuilders
                .groupByComposite("groupByComposite")
                .size(2000)
                .addSources(GroupByBuilders.groupByField("groupByField", "Col_Keyword")
                        .addGroupBySorter(GroupBySorter.groupKeySortInAsc()).build())
                .addSources(GroupByBuilders.groupByHistogram("groupByHistogram", "Col_Long")
                        .addGroupBySorter(GroupBySorter.groupKeySortInAsc())
                        .interval(5)
                        .build())
                .addSources(GroupByBuilders.groupByDateHistogram("groupByDateHistogram", "Col_Date")
                        .addGroupBySorter(GroupBySorter.groupKeySortInAsc())
                        .interval(5, DateTimeUnit.DAY)
                        .timeZone("+05:30").build());
    
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .indexName("<SEARCH_INDEX_NAME>")
                .tableName("<TABLE_NAME>")
                .returnAllColumnsFromIndex(true)
                .searchQuery(SearchQuery.newBuilder()
                        .addGroupBy(compositeBuilder.build())
                        .build())
                .build();
    
        SearchResponse resp = client.search(searchRequest);
    
        while (true) {
            if (resp.getGroupByResults() == null || resp.getGroupByResults().getResultAsMap().size() == 0) {
                System.out.println("groupByComposite Result is null or empty");
                return;
            }
    
            GroupByCompositeResult result = resp.getGroupByResults().getAsGroupByCompositeResult("groupByComposite");
    
            if(!result.getSourceNames().isEmpty()) {
                for (String sourceGroupByNames: result.getSourceNames()) {
                    System.out.printf("%s\t", sourceGroupByNames);
                }
                System.out.print("rowCount\t\n");
            }
    
    
            for (GroupByCompositeResultItem item : result.getGroupByCompositeResultItems()) {
                for (String value : item.getKeys()) {
                    String val = value == null ? "NULL" : value;
                    System.out.printf("%s\t", val);
    
                }
                System.out.printf("%d\t\n", item.getRowCount());
            }
    
            // 利用token,繼續翻頁獲取后續分組
            if (result.getNextToken() != null) {
                searchRequest.setSearchQuery(
                        SearchQuery.newBuilder()
                                .addGroupBy(compositeBuilder.nextToken(result.getNextToken()).build())
                                .build()
                );
                resp = client.search(searchRequest);
            } else {
                break;
            }
        }
    }

范圍分組

根據一個字段的范圍對查詢結果進行分組,字段值在某范圍內放到同一分組內,返回每個范圍中相應的item個數。

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long和Double類型。

    range[double_from, double_to)

    分組的范圍。

    起始值double_from可以使用最小值Double.MIN_VALUE,結束值double_to可以使用最大值Double.MAX_VALUE。

    subAggregation和subGroupBy

    子統計聚合,子統計聚合會根據分組內容再進行一次統計聚合分析。

    例如按銷量分組后再按省份分組,即可獲得某個銷量范圍內哪個省比重比較大,實現方法是GroupByRange下添加一個GroupByField。

  • 示例

    /**
     * 求商品銷量時按[0,1000)、[1000,5000)、[5000,Double.MAX_VALUE)這些分組計算每個范圍的銷量。
     */
    public void groupByRange(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .searchQuery(
                SearchQuery.newBuilder()
                    .query(QueryBuilders.matchAll())
                    .limit(0)
                    .addGroupBy(GroupByBuilders
                        .groupByRange("name1", "column_number")
                        .addRange(0, 1000)
                        .addRange(1000, 5000)
                        .addRange(5000, Double.MAX_VALUE)
                    )
                    .build())
            .build();
        //執行查詢。
        SearchResponse resp = client.search(searchRequest);
        //獲取統計聚合結果。
        for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name1").getGroupByRangeResultItems()) {
    
            //打印個數。
            System.out.println(item.getRowCount());
        }
    }

地理位置分組

根據距離某一個中心點的范圍對查詢結果進行分組,距離差值在某范圍內放到同一分組內,返回每個范圍中相應的item個數。

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Geo_point類型。

    origin(double lat, double lon)

    起始中心點的經緯度。

    double lat是起始中心點緯度,double lon是起始中心點經度。

    range[double_from, double_to)

    分組的范圍,單位為米。

    起始值double_from可以使用最小值Double.MIN_VALUE,結束值double_to可以使用最大值Double.MAX_VALUE。

    subAggregation和subGroupBy

    子統計聚合,子統計聚合會根據分組內容再進行一次統計聚合分析。

  • 示例

    /**
     * 求距離萬達廣場[0,1000)、[1000,5000)、[5000,Double.MAX_VALUE)這些范圍內的人數,距離的單位為米。
     */
    public void groupByGeoDistance(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .searchQuery(
                SearchQuery.newBuilder()
                    .query(QueryBuilders.matchAll())
                    .limit(0)
                    .addGroupBy(GroupByBuilders
                        .groupByGeoDistance("name1", "column_geo_point")
                        .origin(3.1, 6.5)
                        .addRange(0, 1000)
                        .addRange(1000, 5000)
                        .addRange(5000, Double.MAX_VALUE)
                    )
                    .build())
            .build();
        //執行查詢。
        SearchResponse resp = client.search(searchRequest);
        //獲取統計聚合結果。
        for (GroupByGeoDistanceResultItem item : resp.getGroupByResults().getAsGroupByGeoDistanceResult("name1").getGroupByGeoDistanceResultItems()) {
           //打印個數。
            System.out.println(item.getRowCount());
        }
    }

過濾條件分組

按照過濾條件對查詢結果進行分組,獲取每個過濾條件匹配到的數量,返回結果的順序和添加過濾條件的順序一致。

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    filter

    過濾條件,返回結果的順序和添加過濾條件的順序一致。

    subAggregation和subGroupBy

    子統計聚合,子統計聚合會根據分組內容再進行一次統計聚合分析。

  • 示例

    /**
     * 按照過濾條件進行分組,例如添加三個過濾條件(銷量大于100、產地是浙江省、描述中包含杭州關鍵詞),然后獲取每個過濾條件匹配到的數量。
     */
    public void groupByFilter(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .searchQuery(
                SearchQuery.newBuilder()
                    .query(QueryBuilders.matchAll())
                    .limit(0) 
                    .addGroupBy(GroupByBuilders
                        .groupByFilter("name1")
                        .addFilter(QueryBuilders.range("number").greaterThanOrEqual(100))
                        .addFilter(QueryBuilders.term("place","浙江省"))
                        .addFilter(QueryBuilders.match("text","杭州"))
                    )
                    .build())
            .build();
        //執行查詢。
        SearchResponse resp = client.search(searchRequest);
        //按照過濾條件的順序獲取的統計聚合結果。
        for (GroupByFilterResultItem item : resp.getGroupByResults().getAsGroupByFilterResult("name1").getGroupByFilterResultItems()) {
            //打印個數。
            System.out.println(item.getRowCount());
        }
    }

直方圖統計

按照指定數據間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數。

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Long和Double類型。

    interval

    統計間隔。

    fieldRange[min,max]

    統計范圍,與interval參數配合使用限制分組的數量。(fieldRange.max-fieldRange.min)/interval的值不能超過2000。

    minDocCount

    最小行數。當分組中的行數小于最小行數時,不會返回此分組的統計結果。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

  • 示例

    /**
     * 統計不同年齡段用戶數量分布情況。
     */
    public static void groupByHistogram(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
            .tableName("<TABLE_NAME>")
            .indexName("<SEARCH_INDEX_NAME>")
            .searchQuery(
                SearchQuery.newBuilder()
                    .addGroupBy(GroupByBuilders
                        .groupByHistogram("groupByHistogram", "age")
                        .interval(10)
                        .minDocCount(0L)
                        .addFieldRange(0, 99))
                    .build())
            .build();
        //執行查詢。
        SearchResponse resp = ots.search(searchRequest);
        //獲取直方圖的統計聚合結果。
        GroupByHistogramResult results = resp.getGroupByResults().getAsGroupByHistogramResult("groupByHistogram");
        for (GroupByHistogramItem item : results.getGroupByHistogramItems()) {
            System.out.println("key:" + item.getKey().asLong() + " value:" + item.getValue());
        }
    }

日期直方圖統計

對日期字段類型的數據按照指定間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數。

重要

表格存儲Java SDK從5.16.1版本開始支持此功能。

  • 參數

    參數

    說明

    groupByName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    fieldName

    用于統計聚合的字段,僅支持Date類型。

    interval

    統計間隔。

    fieldRange[min,max]

    統計范圍,與interval參數配合使用限制分組的數量。(fieldRange.max-fieldRange.min)/interval的值不能超過2000。

    minDocCount

    最小行數。當分組中的行數小于最小行數時,不會返回此分組的統計結果。

    missing

    當某行數據中的字段為空時,字段值的默認值。

    • 如果未設置missing值,則在統計聚合時會忽略該行。

    • 如果設置了missing值,則使用missing值作為字段值的默認值參與統計聚合。

    timeZone

    時區。格式為+hh:mm或者-hh:mm,例如+08:00-09:00。只有當字段數據類型為Date時才需要配置。

    當Date類型字段的Format未設置時區信息時,可能會導致聚合結果存在N小時的偏移,此時請設置timeZone來解決該問題。

  • 示例

    /**
     * 統計2017-05-01 10:00到2017-05-21 13:00:00時間段內每天的col_date數據分布情況。
     */
    public static void groupByDateHistogram(SyncClient client) {
        //構建查詢語句。
        SearchRequest searchRequest = SearchRequest.newBuilder()
        .returnAllColumns(false)
        .indexName("<SEARCH_INDEX_NAME>")
        .tableName("<TABLE_NAME>")
        .searchQuery(
            SearchQuery.newBuilder()
            .query(QueryBuilders.matchAll())
            .limit(0)
            .getTotalCount(false)
            .addGroupBy(GroupByBuilders
                        .groupByDateHistogram("groupByDateHistogram", "col_date")
                        .interval(1, DateTimeUnit.DAY)
                        .minDocCount(1)
                        .missing("2017-05-01 13:01:00")
                        .fieldRange("2017-05-01 10:00", "2017-05-21 13:00:00"))
            .build())
        .build();
        //執行查詢。
        SearchResponse resp = ots.search(searchRequest);
        //獲取直方圖的統計聚合結果。
        List<GroupByDateHistogramItem> items = resp.getGroupByResults().getAsGroupByDateHistogramResult("groupByDateHistogram").getGroupByDateHistogramItems();
        for (GroupByDateHistogramItem item : items) {
            System.out.printf("millisecondTimestamp:%d, count:%d \n", item.getTimestamp(), item.getRowCount());
        }
    }

獲取統計聚合分組中的行

對查詢結果進行分組后,獲取每個分組內的一些行數據,可實現和MySQL中ANY_VALUE(field)類似的功能。

說明

獲取統計聚合分組中的行時,如果多元索引中包含嵌套類型、地理位置類型或者數組類型的字段,則返回結果中只會包含主鍵信息,請手動反查數據表獲取所需字段。

  • 參數

    參數

    說明

    aggregationName

    自定義的統計聚合名稱,用于區分不同的統計聚合,可根據此名稱獲取本次統計聚合結果。

    limit

    每個分組內最多返回的數據行數,默認返回1行數據。

    sort

    分組內數據的排序方式。

    columnsToGet

    指定返回的字段,僅支持多元索引中的字段,且不支持數組、Date、Geopoint和Nested類型的字段。

    該參數復用SearchRequest中的columnsToGet參數,在SearchRequest中指定columnsToGet即可。

  • 示例

    /**
     * 某學校有一個活動報名表,活動報名表中包含學生姓名、班級、班主任、班長等信息,如果希望按班級進行分組,以查看每個班級的報名情況,同時獲取班級的屬性信息。
     * 等效的SQL語句是select className, teacher, monitor, COUNT(*) as number from table GROUP BY className。
     */
    public void testTopRows(SyncClient client) {
        SearchRequest searchRequest = SearchRequest.newBuilder()
                .indexName("<SEARCH_INDEX_NAME>")
                .tableName("<TABLE_NAME>")
                .searchQuery(
                        SearchQuery.newBuilder()
                                .query(QueryBuilders.matchAll())
                                .limit(0) 
                                .addGroupBy(GroupByBuilders.groupByField("groupName", "className")
                                        .size(5)  //返回的分組數量,最大值請參見“多元索引使用限制”文檔中的限制性“GroupByField返回的分組個數”。
                                        .addSubAggregation(AggregationBuilders.topRows("topRowsName")
                                                .limit(1)
                                                .sort(new Sort(Arrays.asList(new FieldSort("teacher", SortOrder.DESC)))) // topRows的排序
                                        )
                                )
                                .build())
                .addColumnsToGet(Arrays.asList("teacher", "monitor"))
                .build();
        SearchResponse resp = client.search(searchRequest);
        List<GroupByFieldResultItem> items = resp.getGroupByResults().getAsGroupByFieldResult("groupName").getGroupByFieldResultItems();
        for (GroupByFieldResultItem item : items) {
            String className = item.getKey();
            long number = item.getRowCount();
            List<Row> topRows = item.getSubAggregationResults().getAsTopRowsAggregationResult("topRowsName").getRows();
            Row row = topRows.get(0);
            String teacher = row.getLatestColumn("teacher").getValue().asString();
            String monitor = row.getLatestColumn("monitor").getValue().asString();
        }
    }

嵌套

分組類型的統計聚合功能支持嵌套,其內部可以添加子統計聚合。

主要用于在分組內再次進行統計聚合,以兩層的嵌套為例:

  • GroupBy+SubGroupBy:按省份分組后再按照城市分組,獲取每個省份下每個城市的數據。

  • GroupBy+SubAggregation:按照省份分組后再求某個指標的最大值,獲取每個省的某個指標最大值。

說明

為了性能、復雜度等綜合考慮,嵌套的層級只開放了一定的層數。更多信息,請參見多元索引限制

public void subGroupBy(SyncClient client) {
    //構建查詢語句。
    SearchRequest searchRequest = SearchRequest.newBuilder()
            .indexName("<SEARCH_INDEX_NAME>")
            .tableName("<TABLE_NAME>")
            .returnAllColumns(true)
            .searchQuery(
                    SearchQuery.newBuilder()
                            .query(QueryBuilders.match("textField", "hello"))
                            .limit(10)
                            .addAggregation(AggregationBuilders.min("name1", "fieldName1"))
                            .addAggregation(AggregationBuilders.max("name2", "fieldName2"))
                            .addGroupBy(GroupByBuilders
                                    .groupByField("name3", "fieldName3")
                                    .addSubAggregation(AggregationBuilders.max("subName1", "fieldName4"))
                                    .addSubAggregation(AggregationBuilders.sum("subName2", "fieldName5"))
                                    .addSubGroupBy(GroupByBuilders
                                            .groupByRange("subName3", "fieldName6")
                                            .addRange(12, 90)
                                            .addRange(100, 900)
                                    ))
                            .build())
            .build();
    //執行查詢。
    SearchResponse resp = client.search(searchRequest);
    //獲取第一層求最小值和求最大值的統計聚合結果。
    AggregationResults aggResults = resp.getAggregationResults();
    System.out.println(aggResults.getAsMinAggregationResult("name1").getValue());
    System.out.println(aggResults.getAsMaxAggregationResult("name2").getValue());

    //獲取第一層按字段值分組的統計聚合結果,并同時獲取其嵌套的子統計聚合結果。
    GroupByFieldResult results = resp.getGroupByResults().getAsGroupByFieldResult("name3");
    for (GroupByFieldResultItem item : results.getGroupByFieldResultItems()) {
        System.out.println("數量:" + item.getRowCount());
        System.out.println("key:" + item.getKey());

        //獲取子統計聚合結果。
        //打印求最大值的子統計聚合結果。
        System.out.println(item.getSubAggregationResults().getAsMaxAggregationResult("subName1"));
        //打印求和的子統計聚合結果。
        System.out.println(item.getSubAggregationResults().getAsSumAggregationResult("subName2"));
        //打印按范圍分組的子統計聚合結果。
        GroupByRangeResult subResults = item.getSubGroupByResults().getAsGroupByRangeResult("subName3");
        for (GroupByRangeResultItem subItem : subResults.getGroupByRangeResultItems()) {
            System.out.println(String.format("from:%s, to:%s, count:%s", subItem.getFrom(), subItem.getTo(), subItem.getRowCount()));
        }
    }
}

多個統計聚合

多個統計聚合功能可以組合使用。

說明

當多個統計聚合的復雜度較高時可能會影響響應速度。

組合使用多個Aggregation

public void multipleAggregation(SyncClient client) {
    //構建查詢語句。
    SearchRequest searchRequest = SearchRequest.newBuilder()
        .tableName("<TABLE_NAME>")
        .indexName("<SEARCH_INDEX_NAME>")
        .searchQuery(
            SearchQuery.newBuilder()
                .query(QueryBuilders.matchAll())
                .limit(0) 
                .addAggregation(AggregationBuilders.min("name1", "long"))
                .addAggregation(AggregationBuilders.sum("name2", "long"))
                .addAggregation(AggregationBuilders.distinctCount("name3", "long"))
                .build())
        .build();
    //執行查詢。
    SearchResponse resp = client.search(searchRequest);
    //獲取求最小值的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsMinAggregationResult("name1").getValue());
    //獲取求和的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsSumAggregationResult("name2").getValue());
    //獲取去重統計行數的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("name3").getValue());
}

組合使用Aggregation和GroupBy

public void multipleGroupBy(SyncClient client) {
    //構建查詢語句。
    SearchRequest searchRequest = SearchRequest.newBuilder()
        .tableName("<TABLE_NAME>")
        .indexName("<SEARCH_INDEX_NAME>")
        .searchQuery(
            SearchQuery.newBuilder()
                .query(QueryBuilders.matchAll())
                .limit(0)
                .addAggregation(AggregationBuilders.min("name1", "long"))
                .addAggregation(AggregationBuilders.sum("name2", "long"))
                .addAggregation(AggregationBuilders.distinctCount("name3", "long"))
                .addGroupBy(GroupByBuilders.groupByField("name4", "type"))
                .addGroupBy(GroupByBuilders.groupByRange("name5", "long").addRange(1, 15))
                .build())
        .build();
    //執行查詢。
    SearchResponse resp = client.search(searchRequest);
    //獲取求最小值的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsMinAggregationResult("name1").getValue());
    //獲取求和的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsSumAggregationResult("name2").getValue());
    //獲取去重統計行數的統計聚合結果。
    System.out.println(resp.getAggregationResults().getAsDistinctCountAggregationResult("name3").getValue());
    //獲取按字段值分組的統計聚合結果。
    for (GroupByFieldResultItem item : resp.getGroupByResults().getAsGroupByFieldResult("name4").getGroupByFieldResultItems()) {
        //打印key。
        System.out.println(item.getKey());
        //打印個數。
        System.out.println(item.getRowCount());
    }
    //獲取按范圍分組的統計聚合結果。
    for (GroupByRangeResultItem item : resp.getGroupByResults().getAsGroupByRangeResult("name5").getGroupByRangeResultItems()) {
        //打印個數。
        System.out.println(item.getRowCount());
    }
}

附錄:多字段分組不同實現方式對比

如果要根據多個字段對查詢結果進行分組,您可以通過字段分組嵌套(即嵌套多層groupBy)或者多字段分組(即直接使用GroupByComposite)功能實現。具體實現方式的功能對比說明請參見下表。

功能對比

字段分組嵌套

多字段分組

size

2000

2000

字段列限制

最高支持5層

最高支持32列

翻頁

不支持

支持通過GroupByComposite中的nextToken翻頁

分組中Item排序規則

  • 按照值的字典序升序或降序排列

  • 按照行數升序或降序排列

  • 按照子統計聚合結果中值升序或降序排列

按照值的字典序升序或降序排列

是否支持子統計聚合

支持

支持

兼容性

日期類型根據format返回

日期類型返回時間戳字符串

相關文檔

您還可以通過以下查詢與分析表中數據。

  • 使用表格存儲的SQL查詢功能。更多信息,請參見SQL查詢

  • 通過對接DataWorks等大數據平臺實現使用SQL查詢與分析數據。更多信息,請參見大數據對接

  • 通過對接MaxCompute、Spark、Hive或者HadoopMR、函數計算、Flink、PrestoDB等計算引擎實現。更多信息,請參見計算與分析概述