すべてのプロダクト
Search
ドキュメントセンター

Tablestore:Sort and paginate results

最終更新日:Jul 29, 2026

Tablestore SDK for Java を使用して多次元インデックスをクエリする場合、インデックスソートまたはクエリタイムソートを使用して結果の順序を制御し、オフセットまたはトークンを使用して結果をページ分割します。

前提条件

Tablestore SDK for Java をインストールして、クライアントを初期化します。

仕組み

検索インデックスは、以下のソートメカニズムに対応しています:

  • インデックスソート:多次元インデックスを作成する際に、IndexSchema.indexSort を構成してデフォルトの結果順序を定義します。インデックスソートが構成されていない場合、結果はプライマリキーでソートされます。インデックスソートは PrimaryKeySortFieldSort のみをサポートします。Nested フィールドを含む多次元インデックスは、インデックスソートをサポートしません。

  • クエリタイムソート:個別のクエリに対して SearchQuery.sort を構成します。結果は、関連性スコア、プライマリキー、フィールド値、または地理的距離によってソートできます。複数のソーターを組み合わせて、複数レベルのソートを行うことも可能です。プライマリキーフィールドを除き、ソートフィールドは多次元インデックススキーマで enableSortAndAggtrue に設定する必要があります。

プライマリキーソーター以外のクエリタイムソーターが指定された場合、サーバーはデフォルトでプライマリキーソーターを追加し、同じソート値を持つ行が確定的な順序になるようにします。この動作を無効にするには、Sort.disableDefaultPkSortertrue に設定します。

大規模な結果セットには、次のいずれかのページネーションメソッドを使用します。

メソッド

ユースケース

特徴

limit と offset

結果セットが 100,000 行以下で、特定の位置にアクセスする必要がある場合。

ページジャンプをサポートします。limitoffset の合計は 100,000 を超えることはできません。

トークン

ディープページネーション、またはすべての結果を順次読み取る場合。

100,000 行の深さ制限はありませんが、結果は順次読み取りしかできません。

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

クエリタイムソートの構成です。このパラメーターが構成されていない場合、インデックスソートが使用されます。トークンベースのページネーションでは、このパラメーターを構成しないでください。setToken が呼び出されると、SDK は既存のソート構成をクリアします。

offset (任意)

Integer

現在のクエリが開始される位置です。デフォルト値:0。このパラメーターは、トークンベースのページネーションでは構成できません。

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>

ソーターのリストです。リストの順序によって、複数レベルのソートの優先度が決まります。サポートされているソーターは ScoreSortPrimaryKeySortFieldSort、および GeoDistanceSort です。

disableDefaultPkSorter (任意)

Boolean

サーバーが自動的にプライマリキーソーターを追加するのを防ぐかどうかを指定します。デフォルト値:false

関連性スコアによるソート

ScoreSort は、BM25 アルゴリズムを使用して計算された関連性スコアで行をソートします。次の表にそのパラメーターを示します。

名前

タイプ

説明

order (任意)

SortOrder

ソート順です。ASC は昇順を指定し、DESC は降順を指定します。デフォルト値:DESC

関連性スコアでソートするには、明示的に ScoreSort を構成します。そうしない場合、インデックスソートが使用されます。

プライマリキーによるソート

PrimaryKeySort は、プライマリキーで行をソートします。次の表にそのパラメーターを示します。

名前

タイプ

説明

order (任意)

SortOrder

ソート順です。デフォルト値:ASC

フィールドによるソート

FieldSort は、フィールド値で行をソートします。次の表にそのパラメーターを示します。

名前

タイプ

説明

fieldName (必須)

String

ソートフィールドの名前です。フィールドに対してソートと集約を有効にする必要があります。

order (任意)

SortOrder

ソート順です。デフォルト値:ASC

mode (任意)

SortMode

複数値フィールドをソートするときに使用する値です。MINMAX、および 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

複数の距離が存在する場合に使用する値です。サポートされている値は MINMAX、および AVG です。

distanceType (任意)

GeoDistanceType

距離計算メソッドです。ARC は球面計算を実行して精度を高めます。PLANE は計算量が少ない平面計算を実行します。デフォルト値:ARC

nestedFilter (任意)

NestedFilter

Nested ソート構成です。このパラメーターは、Nested サブフィールドをソートする場合にのみ構成します。

返される列

request.columnsToGet のタイプは SearchRequest.ColumnsToGet です。返される列がデータテーブルから読み取られる必要があるかどうかは、limit の最大値に影響します。

名前

タイプ

説明

columns (任意)

List<String>

返す属性列の名前です。指定されたすべての属性列がインデックス化され、ストアが有効になっている場合にのみ、データを多次元インデックスから直接読み取ることができます。

returnAll (任意)

boolean

データテーブル内のすべての属性列を返すかどうかを指定します。デフォルト値:false。このパラメーターが true の場合、属性列はデータテーブルから読み取られる必要があり、limit の最大値は 100 です。

returnAllFromIndex (任意)

boolean

検索インデックスに保存されているすべての属性列を返すかどうかを指定します。デフォルト値: false。このパラメーターが true の場合、上限値は 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 フィールドをインデックスソートフィールドとして構成します。クエリにソートが構成されていない場合、結果は 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 行を返します。このメソッドを使用する場合、limitoffset の合計は 100,000 を超えることはできません。

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

トークンを使用したページネーション

次の例では、ループですべての結果を読み取ります。最初のクエリではトークンは null です。後続の各クエリは、前の応答の nextToken を直接使用します。setToken が呼び出されると、トークンには前のページのソート条件が含まれているため、SDK はソートをクリアします。

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);
重要
  • トークンベースのページネーションでは、オフセットを構成できず、ページをスキップすることもできません。前のページに戻るには、各ページのリクエストに使用したトークンをキャッシュし、対象ページのトークンを使用して再度クエリを発行します。

  • Nested フィールドを含む多次元インデックスには、インデックスソートがありません。このタイプのインデックスでトークンベースのページネーションを使用するには、最初のクエリで明示的にソートを構成する必要があります。そうしないと、サーバーは nextToken を返しません。

同一プロセス内でのシーケンシャルなクエリでは、nextToken をバイト配列として直接渡します。Base64 エンコーディングは、トークンを永続化したり、プロセス間やフロントエンドとバックエンド間で転送したりする必要がある場合にのみ使用してください。new String(nextToken) を使用してトークンを変換しないでください。トークンが破損する原因となります。

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