全部產品
Search
文件中心

Tablestore:排序和翻頁

更新時間:Jul 29, 2026

使用 Tablestore Java SDK 查詢多元索引時,可通過索引預排序或查詢時排序控制結果順序,並通過 offset 或 token 分頁讀取結果。

前提條件

安裝Tablestore Java SDK並初始化用戶端。

功能說明

多元索引支援以下排序方式:

  • 索引預排序:建立多元索引時,通過 IndexSchema.indexSort 設定預設返回順序。未設定時,預設按照主鍵排序。索引預排序僅支援 PrimaryKeySort 和 FieldSort,包含 Nested 欄位的多元索引不支援索引預排序。

  • 查詢時排序:通過 SearchQuery.sort 為單次查詢設定返回順序,支援按相關性得分、主鍵、欄位值或地理距離排序,也支援組合多個排序器實現多級排序。除主鍵外,排序欄位必須在建立多元索引時將 enableSortAndAgg 設定為 true。

查詢時指定非主鍵排序器後,服務端預設追加主鍵排序器,使排序值相同的資料保持確定的返回順序。設定 Sort.disableDefaultPkSorter 為 true 可禁用該行為。

返回結果較多時,可使用以下方式分頁:

方式

適用情境

特點

limit 和 offset

結果不超過 100000 行,需要跳轉到指定位置。

可跳頁,limit + offset 不能超過 100000。

token

深度分頁或順序讀取全部結果。

翻頁深度不受 100000 行限制,但只能按順序讀取。

調用 search 方法查詢資料。

SearchResponse search(SearchRequest request)

以下樣本按照 score 欄位降序、主鍵升序返回前 10 行資料。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setLimit(10);
searchQuery.setSort(new Sort(Arrays.<Sort.Sorter>asList(
        new FieldSort("score", SortOrder.DESC),
        new PrimaryKeySort(SortOrder.ASC))));

SearchRequest request =
        new SearchRequest("example_table", "example_index", searchQuery);
SearchResponse response = client.search(request);

參數說明

查詢請求

request 的類型為 SearchRequest,包含以下參數。

名稱

類型

說明

tableName(必選)

String

資料表名稱。

indexName(必選)

String

多元索引名稱。

searchQuery(必選)

SearchQuery

查詢條件、排序和分頁配置。

columnsToGet(可選)

SearchRequest.ColumnsToGet

返回列配置。未設定時只返回主鍵列。

查詢配置

request.searchQuery 的類型為 SearchQuery。以下僅列出與排序和翻頁相關的參數。

名稱

類型

說明

query(必選)

Query

查詢條件。

sort(可選)

Sort

查詢時排序配置。未設定時按照索引預排序返回。使用 token 翻頁時無需設定,調用 setToken 後 SDK 會清除已有的 sort 配置。

offset(可選)

Integer

本次查詢的起始位置。預設值為 0。使用 token 翻頁時不能設定。

limit(可選)

Integer

本次查詢返回的最大行數。預設值為 10。僅從多元索引讀取返回列時最大值為 1000;任一返回列需要從資料表讀取時最大值為 100。

token(可選)

byte[]

翻頁憑證。將上一次響應的 nextToken 設定為該參數可繼續讀取後續資料。

trackTotalCount(可選)

int

期望統計的最大匹配行數。預設值為 TRACK_TOTAL_COUNT_DISABLED,表示不統計;設定為 TRACK_TOTAL_COUNT 時統計全部匹配行。值越小,查詢效能越高。

排序配置

request.searchQuery.sort 的類型為 Sort,包含以下參數。

名稱

類型

說明

sorters(必選)

List<Sort.Sorter>

排序器列表。列表順序決定多級排序的優先順序。支援 ScoreSort、PrimaryKeySort、FieldSort 和 GeoDistanceSort。

disableDefaultPkSorter(可選)

Boolean

是否禁止自動追加主鍵排序器。預設值為 false。

相關性排序

ScoreSort 按照 BM25 演算法計算的相關性得分排序,包含以下參數。

名稱

類型

說明

order(可選)

SortOrder

排序方向。ASC 表示升序,DESC 表示降序。預設值為 DESC。

如需按照相關性得分排序,必須顯式設定 ScoreSort,否則按照索引預排序返回。

主鍵排序

PrimaryKeySort 按照主鍵排序,包含以下參數。

名稱

類型

說明

order(可選)

SortOrder

排序方向。預設值為 ASC。

欄位排序

FieldSort 按照欄位值排序,包含以下參數。

名稱

類型

說明

fieldName(必選)

String

排序欄位名稱。欄位必須啟用排序與統計彙總。

order(可選)

SortOrder

排序方向。預設值為 ASC。

mode(可選)

SortMode

多重值欄位參與排序的取值方式。MIN、MAX 和 AVG 分別表示使用最小值、最大值和平均值。

missingFields(可選)

List<String>

備用排序欄位列表。當前排序欄位缺失時,按列表順序使用首個存在的欄位值參與排序。備用欄位必須與排序欄位類型相同。

missingValue(可選)

ColumnValue

排序欄位及備用欄位均缺失時使用的排序值。設定為 FIRST_WHEN_MISSING 或 LAST_WHEN_MISSING 可將缺失行固定在最前或最後,也可設定與欄位類型相同的自訂值。未設定時缺失行排在最後。

nestedFilter(可選)

NestedFilter

Nested 子欄位排序配置,用於指定 Nested 路徑和參與排序的子行。僅對 Nested 子欄位排序時設定。

Nested 過濾

FieldSort.nestedFilter 的類型為 NestedFilter,包含以下參數。

名稱

類型

說明

path(必選)

String

Nested 欄位路徑。

query(必選)

Query

用於篩選參與排序的 Nested 子行的查詢條件。設定為 MatchAllQuery 時使用全部子行。

地理距離排序

GeoDistanceSort 按照地理點與目標點之間的距離排序,包含以下參數。

名稱

類型

說明

fieldName(必選)

String

Geopoint 排序欄位名稱。

points(必選)

List<String>

目標地理點列表。地理點使用 緯度,經度 格式。

order(可選)

SortOrder

排序方向。ASC 表示距離由近到遠,DESC 表示由遠到近。

mode(可選)

SortMode

存在多個距離時參與排序的取值方式。支援 MIN、MAX 和 AVG。

distanceType(可選)

GeoDistanceType

距離計算方式。ARC 按球面計算,精度較高;PLANE 按平面計算,計算量較小。預設值為 ARC。

nestedFilter(可選)

NestedFilter

Nested 子欄位排序配置。僅對 Nested 子欄位排序時設定。

返回列

request.columnsToGet 的類型為 SearchRequest.ColumnsToGet。返回列是否需要從資料表讀取會影響 limit 上限。

名稱

類型

說明

columns(可選)

List<String>

要返回的屬性列名稱。僅返回已建立索引且開啟 store 的屬性列時,資料可直接從多元索引讀取。

returnAll(可選)

boolean

是否返回資料表中的全部屬性列。預設值為 false。設定為 true 時需要從資料表讀取屬性列,limit 最大值為 100。

returnAllFromIndex(可選)

boolean

是否返回多元索引中已儲存的全部屬性列。預設值為 false。設定為 true 時 limit 最大值為 1000。不能與 returnAll 同時設定為 true。

傳回值

search 方法返回 SearchResponse。與排序和翻頁相關的核心欄位如下。

名稱

類型

說明

rows

List<Row>

本次查詢返回的行資料,通過 getRows() 擷取,數量不超過 limit。

searchHits

List<SearchHit>

查詢命中結果,通過 getSearchHits() 擷取。

totalCount

long

匹配行數,通過 getTotalCount() 擷取。傳回值取決於 trackTotalCount 配置,不是本頁返回行數。

nextToken

byte[]

下一頁憑證,通過 getNextToken() 擷取。值為 null 表示沒有更多資料,或當前查詢沒有確定的排序方式。

isAllSuccess

boolean

是否已成功查詢全部索引分割區,通過 isAllSuccess() 擷取。值為 false 時返回的是部分結果。

情境樣本

設定索引預排序

建立多元索引時,以下樣本將 score 欄位設定為索引預排序欄位。未在查詢中指定 sort 時,結果預設按照 score 升序返回。

FieldSchema score = new FieldSchema("score", FieldType.LONG)
        .setEnableSortAndAgg(true);

IndexSchema indexSchema = new IndexSchema();
indexSchema.setFieldSchemas(Collections.singletonList(score));
indexSchema.setIndexSort(new Sort(
        Collections.<Sort.Sorter>singletonList(
                new FieldSort("score", SortOrder.ASC))));

按相關性得分排序

以下樣本按照 BM25 相關性得分降序返回結果。

TermQuery termQuery = new TermQuery();
termQuery.setFieldName("category");
termQuery.setTerm(ColumnValue.fromString("book"));

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(termQuery);
searchQuery.setSort(new Sort(
        Collections.<Sort.Sorter>singletonList(new ScoreSort())));

處理欄位值缺失

以下樣本按照 score 欄位降序排序。某行缺少該欄位時,使用 score_backup 的值;兩個欄位均缺失時,將該行排在最後。

FieldSort fieldSort = new FieldSort("score", SortOrder.DESC);
fieldSort.setMissingFields(Collections.singletonList("score_backup"));
fieldSort.setMissingValue(FieldSort.LAST_WHEN_MISSING);

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setSort(new Sort(
        Collections.<Sort.Sorter>singletonList(fieldSort)));

對多值和 Nested 欄位排序

對數組等多重值欄位排序時,通過 mode 指定參與排序的值。以下樣本使用 scores 數組中的最大值進行降序排序。

FieldSort fieldSort = new FieldSort("scores", SortOrder.DESC);
fieldSort.setMode(SortMode.MAX);

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setSort(new Sort(
        Collections.<Sort.Sorter>singletonList(fieldSort)));

對 Nested 子欄位排序時,還需設定 Nested 路徑和參與排序的子行。以下樣本僅使用 items.age 等於 1 的子行,並按照 items.name 的最小值升序排序。

TermQuery ageQuery = new TermQuery();
ageQuery.setFieldName("items.age");
ageQuery.setTerm(ColumnValue.fromLong(1));

FieldSort fieldSort = new FieldSort("items.name", SortOrder.ASC);
fieldSort.setMode(SortMode.MIN);
fieldSort.setNestedFilter(new NestedFilter("items", ageQuery));

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setSort(new Sort(
        Collections.<Sort.Sorter>singletonList(fieldSort)));

按地理距離排序

以下樣本按照 location 欄位與 30.23,120.19 之間的球面距離,由近到遠返回結果。

GeoDistanceSort geoSort = new GeoDistanceSort(
        "location", Collections.singletonList("30.23,120.19"));
geoSort.setOrder(SortOrder.ASC);
geoSort.setDistanceType(GeoDistanceType.ARC);

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setSort(new Sort(
        Collections.<Sort.Sorter>singletonList(geoSort)));

使用 limit 和 offset 翻頁

以下樣本跳過前 100 行,返回後續 100 行。使用該方式時,limit + offset 不能超過 100000。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setQuery(new MatchAllQuery());
searchQuery.setLimit(100);
searchQuery.setOffset(100);

使用 token 翻頁

以下樣本迴圈讀取全部結果。首次查詢將 token 設定為 null;後續查詢直接使用上一次響應中的 nextToken。調用 setToken 後,SDK 會清除 sort,因為 token 已包含上一頁的排序條件。

List<Row> rows = new ArrayList<Row>();
byte[] nextToken = null;
do {
    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(new MatchAllQuery());
    searchQuery.setLimit(100);
    searchQuery.setToken(nextToken);

    SearchRequest request =
            new SearchRequest("example_table", "example_index", searchQuery);
    SearchResponse response = client.search(request);
    rows.addAll(response.getRows());
    nextToken = response.getNextToken();
} while (nextToken != null);
重要
  • 使用 token 翻頁時不能設定 offset,也不能跳頁。需要向前翻頁時,可緩衝各頁請求所用的 token,並使用目標頁對應的 token 重新發起查詢。

  • 包含 Nested 欄位的多元索引沒有索引預排序。使用此類索引進行 token 翻頁時,必須在首次查詢中顯式設定 sort,否則服務端不返回 nextToken。

在同一進程中連續查詢時,直接傳遞 byte[] 類型的 nextToken。僅在需要持久化或跨進程、前後端傳輸時,使用 Base 64 編碼;不能使用 new String(nextToken) 轉換,否則會損壞 token。

String encodedToken = Base64.getEncoder().encodeToString(nextToken);
byte[] decodedToken = Base64.getDecoder().decode(encodedToken);