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

統計聚合

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

流程

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

fig_agg_pro

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

背景信息

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

功能

說明

最小值

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

最大值

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

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

平均值

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

統計行數

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

去重統計行數

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

百分位統計

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

字段值分組

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

說明

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

范圍分組

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

地理位置分組

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

過濾條件分組

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

直方圖統計

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

日期直方圖統計

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

獲取統計聚合分組中的行

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

嵌套

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

多個統計聚合

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

說明

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

前提條件

  • 已初始化 OTSClient。具體操作,請參見初始化 OTSClient

  • 已創建數據表并寫入數據。具體操作,請參見創建數據表寫入數據

  • 已在數據表上創建多元索引。具體操作,請參見創建多元索引

    重要

    統計聚合功能支持的字段類型屬于多元索引的字段類型。關于多元索引的字段類型介紹以及多元索引字段類型和數據表字段類型的映射關系的更多信息,請參見數據類型介紹

最小值

返回一個字段中的最小值,類似于 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("<SEARCH_INDEX_NAME>")
                    .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 版本開始支持此功能。關于 Java SDK 歷史迭代版本的更多信息,請參見 Java SDK 歷史迭代版本

  • 參數

    參數

    說明

    groupByName

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

    fieldName

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

    重要

    表格存儲 Java SDK 版本從 5.13.9 版本開始支持多元索引 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 等計算引擎實現。更多信息,請參見計算與分析概述