統(tǒng)計聚合
通過統(tǒng)計聚合接口可以實現(xiàn)求最小值、求最大值、求和、求平均值、統(tǒng)計行數(shù)、去重統(tǒng)計行數(shù)、按字段值分組、按范圍分組、按地理位置分組、按過濾條件分組、直方圖統(tǒng)計、日期直方圖統(tǒng)計、嵌套功能;同時支持多個統(tǒng)計聚合功能組合使用,滿足復雜的查詢需求。
背景信息
統(tǒng)計聚合的詳細功能請參見下表。
功能 | 說明 |
最小值 | 返回一個字段中的最小值,類似于SQL中的min。 |
最大值 | 返回一個字段中的最大值,類似于SQL中的max。 |
和 | 返回數(shù)值字段的總數(shù),類似于SQL中的sum。 |
平均值 | 返回數(shù)值字段的平均值,類似于SQL中的avg。 |
統(tǒng)計行數(shù) | 返回指定字段值的數(shù)量或者多元索引數(shù)據(jù)總行數(shù),類似于SQL中的count。 |
去重統(tǒng)計行數(shù) | 返回指定字段不同值的數(shù)量,類似于SQL中的count(distinct)。 |
字段值分組 | 根據(jù)一個字段的值對查詢結果進行分組,相同的字段值放到同一分組內,返回每個分組的值和該值對應的個數(shù)。 說明 當分組較大時,按字段值分組可能會存在誤差。 |
多字段分組 | 根據(jù)多個字段對查詢結果進行分組,支持使用token進行翻頁。 |
范圍分組 | 根據(jù)一個字段的范圍對查詢結果進行分組,字段值在某范圍內放到同一分組內,返回每個范圍中相應的item個數(shù)。 |
地理位置分組 | 根據(jù)距離某一個中心點的范圍對查詢結果進行分組,距離差值在某范圍內放到同一分組內,返回每個范圍中相應的item個數(shù)。 |
過濾條件分組 | 按照過濾條件對查詢結果進行分組,獲取每個過濾條件匹配到的數(shù)量,返回結果的順序和添加過濾條件的順序一致。 |
直方圖統(tǒng)計 | 按照指定數(shù)據(jù)間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數(shù)。 |
日期直方圖統(tǒng)計 | 對日期字段類型的數(shù)據(jù)按照指定間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數(shù)。 |
嵌套 | 分組類型的統(tǒng)計聚合功能支持嵌套,其內部可以添加子統(tǒng)計聚合。 |
多個統(tǒng)計聚合 | 多個統(tǒng)計聚合功能可以組合使用。 說明 當多個統(tǒng)計聚合的復雜度較高時可能會影響響應速度。 |
前提條件
已初始化Client。具體操作,請參見初始化OTSClient。
已創(chuàng)建數(shù)據(jù)表并寫入數(shù)據(jù)。具體操作,請參見創(chuàng)建數(shù)據(jù)表和寫入數(shù)據(jù)。
已在數(shù)據(jù)表上創(chuàng)建多元索引。具體操作,請參見創(chuàng)建多元索引。
最小值
返回一個字段中的最小值,類似于SQL中的min。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double和Date類型。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置Missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了Missing值,則使用Missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
/** * 商品庫中有每一種商品的價格,求產(chǎn)地為浙江省的商品中,價格最低的商品價格是多少。 * 等效的SQL語句是SELECT min(column_price) FROM product where place_of_production="浙江省"; */ func min(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewMinAggregation("min_agg_1", "column_price").Missing(0.00))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.Min("min_agg_1") //獲取名稱為"min_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } if agg1.HasValue() { //名稱為"min_agg_1"的統(tǒng)計聚合結果是否有Value值。 fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 } }
最大值
返回一個字段中的最大值,類似于SQL中的max。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double和Date類型。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置Missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了Missing值,則使用Missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
/** * 商品庫中有每一種商品的價格,求產(chǎn)地為浙江省的商品中,價格最高的商品價格是多少。 * 等效的SQL語句是SELECT max(column_price) FROM product where place_of_production="浙江省"。 */ func max(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewMaxAggregation("max_agg_1", "column_price").Missing(0.00))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.Max("max_agg_1") //獲取名稱為"max_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } if agg1.HasValue() { //名稱為"max_agg_1"的統(tǒng)計聚合結果是否有Value值。 fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 } }
和
返回數(shù)值字段的總數(shù),類似于SQL中的sum。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long和Double類型。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置Missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了Missing值,則使用Missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
/** * 商品庫中有每一種商品的售出數(shù)量,求產(chǎn)地為浙江省的商品中,一共售出了多少件商品。如果某一件商品沒有該值,默認售出了10件。 * 等效的SQL語句是SELECT sum(column_price) FROM product where place_of_production="浙江省"。 */ func sum(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewSumAggregation("sum_agg_1", "column_price").Missing(0.00))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.Sum("sum_agg_1") //獲取名稱為"sum_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 }
平均值
返回數(shù)值字段的平均值,類似于SQL中的avg。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double和Date類型。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置Missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了Missing值,則使用Missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
/** * 商品庫中有每一種商品的售出數(shù)量,求產(chǎn)地為浙江省的商品中,平均價格是多少。 * 等效的SQL語句是SELECT avg(column_price) FROM product where place_of_production="浙江省"。 */ func avg(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewAvgAggregation("avg_agg_1", "column_price").Missing(0.00))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.Avg("avg_agg_1") //獲取名稱為"avg_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } if agg1.HasValue() { //名稱為"agg1"的統(tǒng)計聚合結果是否有Value值。 fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 } }
統(tǒng)計行數(shù)
返回指定字段值的數(shù)量或者多元索引數(shù)據(jù)總行數(shù),類似于SQL中的count。
通過如下方式可以統(tǒng)計多元索引數(shù)據(jù)總行數(shù)或者某個query匹配的行數(shù)。
使用統(tǒng)計聚合的count功能,在請求中設置count(*)。
使用query功能的匹配行數(shù),在query中設置setGetTotalCount(true);如果需要統(tǒng)計多元索引數(shù)據(jù)總行數(shù),則使用MatchAllQuery。
如果需要獲取多元索引數(shù)據(jù)某列出現(xiàn)的次數(shù),則使用count(列名),可應用于稀疏列的場景。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double、Boolean、Keyword、Geo_point和Date類型。
示例
/** * 商家?guī)熘杏忻恳环N商家的懲罰記錄,求浙江省的商家中,有懲罰記錄的一共有多少個商家。如果商家沒有懲罰記錄,則商家信息中不存在該字段。 * 等效的SQL語句是SELECT count(column_history) FROM product where place_of_production="浙江省"。 */ func count(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewCountAggregation("count_agg_1", "column_price"))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.Count("count_agg_1") //獲取名稱為"count_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 }
去重統(tǒng)計行數(shù)
返回指定字段不同值的數(shù)量,類似于SQL中的count(distinct)。
去重統(tǒng)計行數(shù)的計算結果是個近似值。
當去重統(tǒng)計行數(shù)小于1萬時,計算結果接近精確值。
當去重統(tǒng)計行數(shù)達到1億時,計算結果的誤差為2%左右。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double、Boolean、Keyword、Geo_point和Date類型。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置Missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了Missing值,則使用Missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
/** * 求所有的商品,產(chǎn)地一共來自多少個省份。 * 等效的SQL語句是SELECT count(distinct column_place) FROM product。 */ func distinctCount(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.TermQuery{"place_of_production", "浙江省"}). SetLimit(0). //如果只關心統(tǒng)計聚合結果,不關心具體數(shù)據(jù),您可以將limit設置為0來提高性能。 Aggregation(search.NewDistinctCountAggregation("distinct_count_agg_1", "column_price").Missing(0.00))) searchResponse, err := client.Search(searchRequest) //執(zhí)行查詢。 aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 agg1, err := aggResults.DistinctCount("distinct_count_agg_1") //獲取名稱為"distinct_count_agg_1"的統(tǒng)計聚合結果。 if err != nil { panic(err) } fmt.Println(agg1.Value) //打印統(tǒng)計聚合結果。 }
字段值分組
根據(jù)一個字段的值對查詢結果進行分組,相同的字段值放到同一分組內,返回每個分組的值和該值對應的個數(shù)。
當分組較大時,按字段值分組可能會存在誤差。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long、Double、Boolean、Keyword和Date類型。
Size
返回的分組數(shù)量,默認值為10。最大值為2000。當分組數(shù)量超過2000時,只會返回前2000個分組。
GroupBySorters
分組中的item排序規(guī)則,默認按照分組中item的數(shù)量降序排序,多個排序則按照添加的順序進行排列。支持的排序類型如下:
按照值的字典序升序排列
按照值的字典序降序排列
按照行數(shù)升序排列
按照行數(shù)降序排列
按照子統(tǒng)計聚合結果中值升序排列
按照子統(tǒng)計聚合結果中值降序排列
SubAggregation和SubGroupBy
子統(tǒng)計聚合,子統(tǒng)計聚合會根據(jù)分組內容再進行一次統(tǒng)計聚合分析。
場景
統(tǒng)計每個類別的商品數(shù)量,且統(tǒng)計每個類別價格的最大值和最小值。
方法
最外層的統(tǒng)計聚合是根據(jù)類別進行分組,再添加兩個子統(tǒng)計聚合求價格的最大值和最小值。
結果示例
水果:5個(其中價格的最大值為15,最小值為3)
洗漱用品:10個(其中價格的最大值為98,最小值為1)
電子設備:3個(其中價格的最大值為8699,最小值為2300)
其它:15個(其中價格的最大值為1000,最小值為80)
示例
/** * 所有商品中每一個類別各有多少個,且統(tǒng)計每一個類別的價格最大值和最小值。 * 返回結果舉例:"水果:5個(其中價格的最大值為15,最小值為3),洗漱用品:10個(其中價格的最大值為98,最小值為1),電子設備:3個(其中價格的最大值為8699,最小值為2300), * 其它:15個(其中價格的最大值為1000,最小值為80)"。 */ func GroupByField(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByField("group1", "column_type"). //按商品類別的字段值進行分組。 SubAggregation(search.NewMinAggregation("min_price", "column_price")). //分組中最便宜的商品。 SubAggregation(search.NewMaxAggregation("max_price", "column_price")))) //分組中最貴的商品。 searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByField("group1") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 //打印分組的值和分組中的記錄行數(shù)。 fmt.Println("\tkey: ", item.Key, ", rowCount: ", item.RowCount) //打印價格的最小值。 minPrice, _ := item.SubAggregations.Min("min_price") if minPrice.HasValue() { fmt.Println("\t\tmin_price: ", minPrice.Value) } //打印價格的最大值。 maxPrice, _ := item.SubAggregations.Max("max_price") if maxPrice.HasValue() { fmt.Println("\t\tmax_price: ", maxPrice.Value) } } }
多字段分組
根據(jù)多個字段對查詢結果進行分組,支持使用token進行翻頁。
要實現(xiàn)多字段分組,您可以通過字段分組嵌套或者多字段分組方式實現(xiàn)。關于兩種實現(xiàn)方式的功能對比,請參見附錄:多字段分組不同實現(xiàn)方式對比。
參數(shù)
參數(shù)
說明
GroupByName
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
SourceGroupByList
多列分組聚合字段對象,最多支持設置32列。支持的分組類型如下:
重要Sources內分組類型的GroupBySorter僅支持groupKeySort,不支持subAggSort和rowCountSort。
默認降序排序。
當某一列字段值不存在時,系統(tǒng)會返回NULL。
字段值分組GroupByField:僅支持設置GroupByName、FieldName和GroupBySorter參數(shù)。
直方圖統(tǒng)計GroupByHistogram:僅支持設置GroupByName、FieldName、Interval和GroupBySorter參數(shù)
日期直方圖統(tǒng)計GroupByDateHistogram:僅支持設置GroupByName、FieldName、Interval、TimeZone和GroupBySorter參數(shù)。
NextToken
進行翻頁時用于繼續(xù)獲取分組的Token值。多列的字段值分組請求結果GroupByCompositeResult中會返回NextToken值,通過NextToken可翻頁獲取全量分組結果。
Size
返回分組的數(shù)量。當滿足條件的分組數(shù)量超過Size限制時,您可以通過NextToken繼續(xù)翻頁獲取分組。
重要當要限制返回的分組數(shù)量時,不支持同時配置Size和SuggestedSize參數(shù)。一般情況下只需配置Size參數(shù)即可。
如果是用于對接例如Spark、Presto等計算引擎的高吞吐場景,則只需配置SuggestedSize參數(shù)。
SuggestedSize
可設置為大于服務端最大限制的值或-1, 服務端按實際能力返回實際行數(shù)。適用于對接例如Spark、Presto等計算引擎的高吞吐場景。
當該值超過服務端最大值限制后會被修正為最大值。實際返回的分組結果數(shù)量為
min(suggestedSize, 服務端分組數(shù)量限制,總分組數(shù)量)
。SubAggList和SubGroupByList
子統(tǒng)計聚合,子統(tǒng)計聚合會根據(jù)分組內容再進行一次統(tǒng)計聚合分析。
重要GroupByComposite不支持作為SubGroupByList。
示例
/** * 組合類型分組聚合:根據(jù)傳入的多個SourceGroupBy(支持groupbyField、groupByHistogram和groupByDataHistogram)進行分組聚合 * 多列的聚合返回結果以扁平化結構返回。 */ func groupByComposite(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByComposite("groupByComposite"). SourceGroupBys(search.NewGroupByField("groupByField_1", "Col_Long"), search.NewGroupByField("groupByField_2", "Col_Keyword"), search.NewGroupByField("groupByField_3", "Col_Double")). SetSize(10))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByComposite("group1") if err != nil { fmt.Printf("%#v", err) return } fmt.Println("groupName: ", group.Name) for _, item := range group.Items { //遍歷返回的所有分組。 //打印分組的值和分組中的記錄行數(shù)。 fmt.Printf("\tkey:") if item.Keys != nil { for i := 0; i < len(item.Keys); i++ { fmt.Printf(" %v ", *item.Keys[i]) } fmt.Printf("\trowCount:%v\n", item.RowCount) } } }
范圍分組
根據(jù)一個字段的范圍對查詢結果進行分組,字段值在某范圍內放到同一分組內,返回每個范圍中相應的item個數(shù)。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Long和Double類型。
Range(fromInclusive float64, toExclusive float64)
分組的范圍。
起始值fromInclusive可以使用最小值NegInf,結束值toExclusive可以使用最大值Inf。
SubAggregation和SubGroupBy
子統(tǒng)計聚合,子統(tǒng)計聚合會根據(jù)分組內容再進行一次統(tǒng)計聚合分析。
例如按銷量分組后再按省份分組,即可獲得某個銷量范圍內哪個省比重比較大,實現(xiàn)方法是GroupByRange下添加一個GroupByField。
示例
/** * 求商品銷量時按[NegInf,1000)、[1000,5000)、[5000,Inf)這些分組計算每個范圍的銷量。 */ func GroupByRange(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByRange("group1", "column_number"). Range(search.NegInf, 1000). Range(1000, 5000). Range(5000, search.Inf))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByRange("group1") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 fmt.Println("\t[", item.From, ", ", item.To, "), rowCount: ", item.RowCount) //打印本次分組的行數(shù)。 } }
地理位置分組
根據(jù)距離某一個中心點的范圍對查詢結果進行分組,距離差值在某范圍內放到同一分組內,返回每個范圍中相應的item個數(shù)。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
FieldName
用于統(tǒng)計聚合的字段,僅支持Geo_point類型。
CenterPoint(latitude float64, longitude float64)
起始中心點的經(jīng)緯度。
latitude是起始中心點坐標緯度,longitude是起始中心點坐標經(jīng)度。
Range(fromInclusive float64, toExclusive float64)
分組的范圍,單位為米。
起始值fromInclusive可以使用最小值NegInf,結束值toExclusive可以使用最大值Inf。
SubAggregation和SubGroupBy
子統(tǒng)計聚合,子統(tǒng)計聚合會根據(jù)分組內容再進行一次統(tǒng)計聚合分析。
示例
/** * 求距離萬達廣場[NegInf,1000)、[1000,5000)、[5000,Inf)這些范圍內的人數(shù),單位為米。 */ func GroupByGeoDistance(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByGeoDistance("group1", "Col_GeoPoint", search.GeoPoint{Lat: 30.137817, Lon:120.08681}). Range(search.NegInf, 1000). Range(1000, 5000). Range(5000, search.Inf))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByGeoDistance("group1") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 fmt.Println("\t[", item.From, ", ", item.To, "), rowCount: ", item.RowCount) //打印本次分組的行數(shù)。 } }
過濾條件分組
按照過濾條件對查詢結果進行分組,獲取每個過濾條件匹配到的數(shù)量,返回結果的順序和添加過濾條件的順序一致。
參數(shù)
參數(shù)
說明
Name
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
Query
過濾條件,返回結果的順序和添加過濾條件的順序一致。
SubAggregation和SubGroupBy
子統(tǒng)計聚合,子統(tǒng)計聚合會根據(jù)分組內容再進行一次統(tǒng)計聚合分析。
示例
/** * 按照過濾條件進行分組,例如添加三個過濾條件(銷量大于100、產(chǎn)地是浙江省、描述中包含杭州關鍵詞),然后獲取每個過濾條件匹配到的數(shù)量。 */ func GroupByFilter(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByFilter("group1"). Query(&search.RangeQuery{ FieldName: "number", From: 100, IncludeLower: true}). Query(&search.TermQuery{ FieldName: "place", Term: "浙江省", }). Query(&search.MatchQuery{ FieldName: "description", Text: "杭州", }))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByFilter("group1") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 fmt.Println("\trowCount: ", item.RowCount) //打印本次分組的行數(shù)。 } }
直方圖統(tǒng)計
按照指定數(shù)據(jù)間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數(shù)。
參數(shù)
參數(shù)
說明
GroupByName
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
Field
用于統(tǒng)計聚合的字段,僅支持Long和Double類型。
Interval
統(tǒng)計間隔。
FieldRange[min,max]
統(tǒng)計范圍,與Interval參數(shù)配合使用限制分組的數(shù)量。
(FieldRange.max-FieldRange.min)/Interval
的值不能超過2000。MinDocCount
最小行數(shù)。當分組中的行數(shù)小于最小行數(shù)時,不會返回此分組的統(tǒng)計結果。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了missing值,則使用missing值作為字段值的默認值參與統(tǒng)計聚合。
示例
func GroupByHistogram(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByHistogram("group1", "field_name"). SetMinDocCount(1). SetFiledRange(1, 100). SetMissing(3). SetInterval(10))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByHistogram("group1") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 fmt.Println("key:", item.Key.Value, ", rowCount:", item.Value) } }
日期直方圖統(tǒng)計
對日期字段類型的數(shù)據(jù)按照指定間隔對查詢結果進行分組,字段值在相同范圍內放到同一分組內,返回每個分組的值和該值對應的個數(shù)。
參數(shù)
參數(shù)
說明
GroupByName
自定義的統(tǒng)計聚合名稱,用于區(qū)分不同的統(tǒng)計聚合,可根據(jù)此名稱獲取本次統(tǒng)計聚合結果。
Field
用于統(tǒng)計聚合的字段,僅支持Date類型。
Interval
統(tǒng)計間隔。
FieldRange[min,max]
統(tǒng)計范圍,與Interval參數(shù)配合使用限制分組的數(shù)量。
(FieldRange.max-FieldRange.min)/Interval
的值不能超過2000。MinDocCount
最小行數(shù)。當分組中的行數(shù)小于最小行數(shù)時,不會返回此分組的統(tǒng)計結果。
Missing
當某行數(shù)據(jù)中的字段為空時,字段值的默認值。
如果未設置missing值,則在統(tǒng)計聚合時會忽略該行。
如果設置了missing值,則使用missing值作為字段值的默認值參與統(tǒng)計聚合。
TimeZone
時區(qū)。格式為
+hh:mm
或者-hh:mm
,例如+08:00
、-09:00
。只有當字段數(shù)據(jù)類型為Date時才需要配置。當Date類型字段的Format未設置時區(qū)信息時,可能會導致聚合結果存在N小時的偏移,此時請設置TimeZone來解決該問題。
示例
func GroupByDateHistogram(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). GroupBy(search.NewGroupByDateHistogram("date_group", "date_field_name"). SetMinDocCount(1). SetFiledRange("2017-05-01 10:00", "2017-05-21 13:00:00"). SetMissing("2017-05-01 13:01:00"). SetInterval(model.DateTimeValue{ Value: proto.Int32(1), Unit: model.DateTimeUnit_DAY.Enum(), }))) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 group, err := groupByResults.GroupByDateHistogram("date_group") if err != nil { fmt.Printf("%#v", err) return } for _, item := range group.Items { //遍歷返回的所有分組。 fmt.Printf("millisecondTimestamp:%d , rowCount:%d \n", item.Timestamp, item.RowCount) } }
嵌套
分組類型的統(tǒng)計聚合功能支持嵌套,其內部可以添加子統(tǒng)計聚合。
主要用于在分組內再次進行統(tǒng)計聚合,以兩層的嵌套為例:
GroupBy+SubGroupBy:按省份分組后再按照城市分組,獲取每個省份下每個城市的數(shù)據(jù)。
GroupBy+SubAggregation:按照省份分組后再求某個指標的最大值,獲取每個省的某個指標最大值。
為了性能、復雜度等綜合考慮,嵌套的層級只開放了一定的層數(shù)。更多信息,請參見多元索引限制。
示例
/**
* 嵌套的統(tǒng)計聚合示例。
* 外層GroupByField中添加了2個Aggregation和1個GroupByRange。
*/
func NestedSample(client *tablestore.TableStoreClient, tableName string, indexName string) {
searchRequest := &tablestore.SearchRequest{}
searchRequest.
SetTableName(tableName). //設置數(shù)據(jù)表名稱。
SetIndexName(indexName). //設置多元索引名稱。
SetSearchQuery(search.NewSearchQuery().
SetQuery(&search.MatchAllQuery{}). //匹配所有行。
SetLimit(0).
GroupBy(search.NewGroupByField("group1", "field1").
SubAggregation(search.NewMinAggregation("sub_agg1", "sub_field1")).
SubAggregation(search.NewMaxAggregation("sub_agg2", "sub_field2")).
SubGroupBy(search.NewGroupByRange("sub_group1", "sub_field3").
Range(search.NegInf, 3).
Range(3, 5).
Range(5, search.Inf))))
searchResponse, err := client.Search(searchRequest)
if err != nil {
fmt.Printf("%#v", err)
return
}
groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。
group, err := groupByResults.GroupByField("group1")
if err != nil {
fmt.Printf("%#v", err)
return
}
for _, item := range group.Items { //遍歷返回的所有分組。
//打印分組的值和分組中的記錄行數(shù)。
fmt.Println("\tkey: ", item.Key, ", rowCount: ", item.RowCount)
//獲取名稱為"sub_agg1"的統(tǒng)計聚合結果。
subAgg1, _ := item.SubAggregations.Min("sub_agg1")
if subAgg1.HasValue() {
fmt.Println("\t\tsub_agg1: ", subAgg1.Value)
}
//獲取名稱為"sub_agg2"的統(tǒng)計聚合結果。
subAgg2, _ := item.SubAggregations.Max("sub_agg2")
if subAgg2.HasValue() {
fmt.Println("\t\tsub_agg2: ", subAgg2.Value)
}
//獲取名稱為"sub_group1"的統(tǒng)計聚合結果。
subGroup, _ := item.SubGroupBys.GroupByRange("sub_group1")
for _, item := range subGroup.Items {
fmt.Println("\t\t[", item.From, ", ", item.To, "), rowCount: ", item.RowCount)
}
}
}
多個統(tǒng)計聚合
多個統(tǒng)計聚合功能可以組合使用。
當多個統(tǒng)計聚合的復雜度較高時可能會影響響應速度。
示例1
func MultipleAggregations(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). Aggregation(search.NewAvgAggregation("agg1", "Col_Long")). //計算Col_Long字段的平均值。 Aggregation(search.NewDistinctCountAggregation("agg2", "Col_Long")). //計算Col_Long字段不同取值的個數(shù)。 Aggregation(search.NewMaxAggregation("agg3", "Col_Long")). //計算Col_Long字段的最大值。 Aggregation(search.NewSumAggregation("agg4", "Col_Long")). //計算Col_Long字段的和。 Aggregation(search.NewCountAggregation("agg5", "Col_Long"))) //計算存在Col_Long字段的行數(shù)。 //設置返回所有列。 searchRequest.SetColumnsToGet(&tablestore.ColumnsToGet{ ReturnAll: true, }) searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 //獲取求平均值的統(tǒng)計聚合結果。 agg1, err := aggResults.Avg("agg1") //獲取名稱為"agg1"的統(tǒng)計聚合結果,類型為Avg。 if err != nil { panic(err) } if agg1.HasValue() { //名稱為"agg1"的統(tǒng)計聚合結果是否有Value值。 fmt.Println("(avg) agg1: ", agg1.Value) //打印Col_Long字段平均值。 } else { fmt.Println("(avg) agg1: no value") //所有行都不存在Col_Long字段時的打印信息。 } //獲取去重統(tǒng)計行數(shù)的統(tǒng)計聚合結果。 agg2, err := aggResults.DistinctCount("agg2") //獲取名稱為"agg2"的統(tǒng)計聚合結果,類型為DistinctCount。 if err != nil { panic(err) } fmt.Println("(distinct) agg2: ", agg2.Value) //打印Col_Long字段不同取值的個數(shù)。 //獲取求最大值的統(tǒng)計聚合結果。 agg3, err := aggResults.Max("agg3") //獲取名稱為"agg3"的統(tǒng)計聚合結果,類型為Max。 if err != nil { panic(err) } if agg3.HasValue() { fmt.Println("(max) agg3: ", agg3.Value) //打印Col_Long字段最大值。 } else { fmt.Println("(max) agg3: no value") //所有行都不存在Col_Long字段時的打印信息。 } //獲取求和的統(tǒng)計聚合結果。 agg4, err := aggResults.Sum("agg4") //獲取名稱為"agg4"的統(tǒng)計聚合結果,類型為Sum。 if err != nil { panic(err) } fmt.Println("(sum) agg4: ", agg4.Value) //打印Col_Long字段的和。 //獲取統(tǒng)計行數(shù)的統(tǒng)計聚合結果。 agg5, err := aggResults.Count("agg5") //獲取名稱為"agg5"的統(tǒng)計聚合結果,類型為Count。 if err != nil { panic(err) } fmt.Println("(count) agg6: ", agg5.Value) //打印存在Col_Long字段的個數(shù)。 }
示例2
func MultipleAggregationsAndGroupBysSample(client *tablestore.TableStoreClient, tableName string, indexName string) { searchRequest := &tablestore.SearchRequest{} searchRequest. SetTableName(tableName). //設置數(shù)據(jù)表名稱。 SetIndexName(indexName). //設置多元索引名稱。 SetSearchQuery(search.NewSearchQuery(). SetQuery(&search.MatchAllQuery{}). //匹配所有行。 SetLimit(0). Aggregation(search.NewAvgAggregation("agg1", "Col_Long")). //計算Col_Long字段的平均值。 Aggregation(search.NewDistinctCountAggregation("agg2", "Col_Long")). //計算Col_Long字段不同取值的個數(shù)。 Aggregation(search.NewMaxAggregation("agg3", "Col_Long")). //計算Col_Long字段的最大值。 GroupBy(search.NewGroupByField("group1", "Col_Keyword"). //對Col_Keyword字段做GroupByField取值統(tǒng)計聚合。 GroupBySorters([]search.GroupBySorter{}). //指定返回結果分組的順序。 Size(2). //僅返回前2個分組。 SubAggregation(search.NewAvgAggregation("sub_agg1", "Col_Long")). //對每個分組進行子統(tǒng)計聚合。 SubGroupBy(search.NewGroupByField("sub_group1", "Col_Keyword2"))). //對每個分組進行子統(tǒng)計聚合。 GroupBy(search.NewGroupByRange("group2", "Col_Long"). //對Col_Long字段做GroupByRange范圍。 Range(search.NegInf, 3). //第一個分組包含Col_Long在(NegInf, 3)的索引行。 Range(3, 5). //第二個分組包含Col_Long在[3, 5)的索引行。 Range(5, search.Inf))) //第三個分組包含Col_Long在[5, Inf)的索引行。 // 設置返回所有列。 searchResponse, err := client.Search(searchRequest) if err != nil { fmt.Printf("%#v", err) return } aggResults := searchResponse.AggregationResults //獲取統(tǒng)計聚合結果。 //獲取求平均值的統(tǒng)計聚合結果。 agg1, err := aggResults.Avg("agg1") //獲取名稱為"agg1"的統(tǒng)計聚合結果,類型為Avg。 if err != nil { panic(err) } if agg1.HasValue() { //名稱為"agg1"的統(tǒng)計聚合結果是否有Value值。 fmt.Println("(avg) agg1: ", agg1.Value) //打印Col_Long字段平均值。 } else { fmt.Println("(avg) agg1: no value") //所有行都不存在Col_Long字段時的打印信息。 } //獲取去重統(tǒng)計行數(shù)的統(tǒng)計聚合結果。 agg2, err := aggResults.DistinctCount("agg2") //獲取名稱為"agg2"的統(tǒng)計聚合結果,類型為DistinctCount。 if err != nil { panic(err) } fmt.Println("(distinct) agg2: ", agg2.Value) //打印Col_Long字段不同取值的個數(shù)。 //獲取求最大值的統(tǒng)計聚合結果。 agg3, err := aggResults.Max("agg3") //獲取名稱為"agg3"的統(tǒng)計聚合結果,類型為Max。 if err != nil { panic(err) } if agg3.HasValue() { fmt.Println("(max) agg3: ", agg3.Value) //打印Col_Long字段最大值。 } else { fmt.Println("(max) agg3: no value") //所有行都不存在Col_Long字段時的打印信息。 } groupByResults := searchResponse.GroupByResults //獲取統(tǒng)計聚合結果。 //獲取按字段值分組的統(tǒng)計聚合結果。 group1, err := groupByResults.GroupByField("group1") //獲取名稱為"group1"的統(tǒng)計聚合結果,類型為GroupByField。 if err != nil { panic(err) } fmt.Println("group1: ") for _, item := range group1.Items { //遍歷返回的所有分組。 //item fmt.Println("\tkey: ", item.Key, ", rowCount: ", item.RowCount) //打印本次分組的行數(shù)。 //獲取求平均值的子統(tǒng)計聚合結果。 subAgg1, err := item.SubAggregations.Avg("sub_agg1") //獲取名稱為"sub_agg1"的子統(tǒng)計聚合結果,類型為Avg。 if err != nil { panic(err) } if subAgg1.HasValue() { //如果子統(tǒng)計聚合"sub_agg1"計算出了Col_Long字段的平均值,則HasValue()返回true。 fmt.Println("\t\tsub_agg1: ", subAgg1.Value) //打印本次分組中,子統(tǒng)計聚合計算的Col_Long字段的平均值。 } //獲取按字段值分組的子統(tǒng)計聚合結果。 subGroup1, err := item.SubGroupBys.GroupByField("sub_group1") //獲取名稱為"sub_group1"的子統(tǒng)計聚合結果,類型為GroupByField。 if err != nil { panic(err) } fmt.Println("\t\tsub_group1") for _, subItem := range subGroup1.Items { //遍歷名稱為"sub_group1"的子統(tǒng)計聚合結果。 fmt.Println("\t\t\tkey: ", subItem.Key, ", rowCount: ", subItem.RowCount) //打印"sub_group1"的子統(tǒng)計聚合結果分組,即分組中的行數(shù)。 tablestore.Assert(subItem.SubAggregations.Empty(), "") tablestore.Assert(subItem.SubGroupBys.Empty(), "") } } //獲取按范圍分組的統(tǒng)計聚合結果。 group2, err := groupByResults.GroupByRange("group2") //獲取名稱為"group2"的統(tǒng)計聚合結果,類型為GroupByRange。 if err != nil { panic(err) } fmt.Println("group2: ") for _, item := range group2.Items { //遍歷返回的所有分組。 fmt.Println("\t[", item.From, ", ", item.To, "), rowCount: ", item.RowCount) //打印本次分組的行數(shù)。 } }
附錄:多字段分組不同實現(xiàn)方式對比
如果要根據(jù)多個字段對查詢結果進行分組,您可以通過字段分組嵌套(即嵌套多層groupBy)或者多字段分組(即直接使用GroupByComposite)功能實現(xiàn)。具體實現(xiàn)方式的功能對比說明請參見下表。
功能對比 | 字段分組嵌套 | 多字段分組 |
size | 2000 | 2000 |
字段列限制 | 最高支持5層 | 最高支持32列 |
翻頁 | 不支持 | 支持通過GroupByComposite中的nextToken翻頁 |
分組中Item排序規(guī)則 |
| 按照值的字典序升序或降序排列 |
是否支持子統(tǒng)計聚合 | 支持 | 支持 |
兼容性 | 日期類型根據(jù)format返回 | 日期類型返回時間戳字符串 |