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

Tablestore:ソートとページングの実行

最終更新日:Mar 26, 2025

検索インデックスを使用してデータをクエリする場合、事前定義されたソート方法を使用するか、ソート方法を指定できます。このようにして、クエリ条件を満たす行は、事前定義または指定した順序に基づいて返されます。 応答に多数の行が含まれている場合は、limit パラメーターと offset パラメーターを設定するか、トークンを使用することで、必要なデータを見つけることができます。

シナリオ

カテゴリ

メソッド

機能

シナリオ

ソート

検索インデックスの作成時にソート方法を事前定義する

インデックスの事前ソート (IndexSort)

デフォルトでは、検索インデックスのデータは、IndexSort パラメーターで指定された事前ソート設定に基づいてソートされます。 IndexSort パラメーターで指定された事前ソート設定は、クエリ条件を満たす行が返されるデフォルトの順序を決定します。

データをクエリするときにソート方法を指定する

BM25 ベースのキーワード関連性スコアに基づくソート (ScoreSort)

ScoreSort を使用して、BM25 ベースのキーワード関連性スコアに基づいてクエリ結果をソートできます。 ScoreSort は、全文検索などのシナリオに適しています。

プライマリキー値に基づくソート (PrimaryKeySort)

PrimaryKeySort を使用して、プライマリキー値に基づいてクエリ結果をソートできます。 PrimaryKeySort は、データの一意の識別子に基づいてデータをソートする場合に適しています。

1 つ以上の列の値に基づくソート (FieldSort)

FieldSort を使用して、1 つ以上の列の値に基づいてクエリ結果をソートできます。 FieldSort は、売上高やページビューなどのプロパティに基づいてデータをソートする場合に適しています。 ほとんどの場合、FieldSort は、E コマース、ソーシャルネットワーキング、メディアアセットなどの業界で使用されます。

Array フィールドや Nested フィールドなどの複数値フィールドに対して FieldSort で mode パラメーターを指定して、クエリ結果のソートに使用する要素を決定できます。

地理的な場所によるソート (GeoDistanceSort)

GeoDistanceSort を使用して、地理的な場所によってクエリ結果をソートできます。 GeoDistanceSort は、特定の場所からの距離に基づいてデータをソートする場合に適しています。 ほとんどの場合、GeoDistanceSort は、マッピングや物流などの業界で使用されます。 たとえば、ある場所の周りのレストランを、その場所からの距離に基づいてソートできます。

ページング

データをクエリするときにページング方法を指定する

limit パラメーターと offset パラメーターに基づくページング

応答の行数が 100,000 未満の場合、この方法を使用してページにジャンプできます。

トークンに基づくページング

この機能を使用すると、データはページごとに返され、後方ページングのみ可能です。 前方ページングを行う場合は、トークンはクエリ中は有効であるため、前のトークンをキャッシュして使用できます。

Tablestore SDK を使用してソートとページングを実行する

次の Tablestore SDK を使用してソートとページングを実行できます。

インデックスの事前ソート

デフォルトでは、検索インデックスのデータは、IndexSort パラメーターで指定された事前ソート設定に基づいてソートされます。 検索インデックスを使用してデータをクエリする場合、IndexSort パラメーターで指定された事前ソート設定によって、一致するデータが返されるデフォルトの順序が決まります。

検索インデックスを作成するときに、IndexSort パラメーターを設定することで、事前ソート設定を指定できます。 事前ソート設定を指定しない場合、検索インデックスのデータはプライマリキー値でソートされます。

重要
  • 検索インデックスの事前ソート方法として、PrimaryKeySort または FieldSort を指定できます。 PrimaryKeySort はプライマリキー値でデータをソートし、FieldSort はフィールド値でデータをソートします。

  • Nested フィールドを含む検索インデックスは、インデックスの事前ソートをサポートしていません。

  • 既存の検索インデックスの IndexSort パラメーターの設定を変更する場合は、検索インデックスのスキーマを動的に変更できます。 詳細については、「検索インデックスのスキーマを動的に変更する」をご参照ください。

データをクエリするときにソート方法を指定する

ソートは、enableSortAndAgg パラメーターが true に設定されているフィールドに対してのみ有効にできます。

クエリごとにソート方法を指定できます。 検索インデックスベースのクエリは、次のソート方法をサポートしています。 優先順位に基づいて複数のソート方法を指定することもできます。

ScoreSort

ScoreSort を使用して、BM25 ベースのキーワード関連性スコアに基づいてクエリ結果をソートできます。 ScoreSort は、全文検索などのシナリオに適しています。

重要
  • 一致するデータをキーワード関連性スコアでソートする前に、ScoreSort のパラメーターを設定する必要があります。 そうしないと、一致するデータは、IndexSort パラメーターで指定された事前ソート設定に基づいてソートされます。

  • ScoreSort を使用する場合、FuzzyKeyword タイプのフィールドはソートに使用されず、weight パラメーターの設定はフィールドに反映されません。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new ScoreSort())));

PrimaryKeySort

PrimaryKeySort を使用して、プライマリキー値に基づいてクエリ結果をソートできます。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort()))); // クエリ結果を昇順にソートします。
//searchQuery.setSort(new Sort(Arrays.asList(new PrimaryKeySort(SortOrder.DESC)))); // クエリ結果を降順にソートします。

FieldSort

FieldSort を使用して、1 つ以上の特定の列の値に基づいてクエリ結果をソートできます。

単一列の値に基づいてクエリ結果をソートする

FieldSort を使用して、特定の列の値に基づいてクエリ結果をソートできます。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(new FieldSort("col", SortOrder.ASC))));

複数列の値に基づいてクエリ結果をソートする

特定の順序で 2 つの列の値に基づいてクエリ結果をソートし、一致するデータが返される順序を決定することもできます。

SearchQuery searchQuery = new SearchQuery();
searchQuery.setSort(new Sort(Arrays.asList(
    new FieldSort("col1", SortOrder.ASC), new FieldSort("col2", SortOrder.ASC))));

補助列の値に基づいてクエリ結果をソートする

Long、Double、または Date 型の列値に基づいてデータをソートする場合、missingField パラメーターを設定して、元の列にデータがない場合に使用される補助列として、同じデータ型の列を指定できます。

/**
* Col_Long 列の値に基づいてクエリ結果を降順にソートします。 Long 型の Col_Long 列のデータがない場合は、同じデータ型の Col_Long_sec 列をソート用の補助列として使用できます。
*/
SearchQuery searchQuery = new SearchQuery();
FieldSort fieldSort = new FieldSort("Col_Long");
// Col_Long 列のデータがない場合のソート用の補助列として、Col_Long_sec 列を指定します。
fieldSort.setMissingField("Col_Long_sec");
fieldSort.setOrder(SortOrder.DESC); 

複数値フィールドの指定された要素に基づいてクエリ結果をソートする

Array フィールドや Nested フィールドなどの複数値フィールドに対して mode パラメーターを指定して、クエリ結果のソートに使用する要素を決定できます。

Array フィールドに対して mode パラメーターを指定して、クエリ結果のソートに使用する要素を決定できます。

// doc1 行と doc2 行には、Array 型の field1 列が含まれています。 doc1 行の field1 列の値は [2,3] で、doc2 行の field1 列の値は [1,3,4] です。
// mode パラメーターを指定して、2 つの行をソートするために使用される 2 つの行の Array フィールドの要素を決定できます。
{
    // mode パラメーターを SortMode.MAX に設定すると、Array フィールドの最大要素を使用して行がソートされます。 この例では、doc1 行の 3 と doc2 行の 4 を使用して 2 つの行がソートされ、ソート結果は doc2 と doc1 になります。
    FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
    fieldSort.setMode(SortMode.MAX);
}
{
    // mode パラメーターを SortMode.MIN に設定すると、Array フィールドの最小要素を使用して行がソートされます。 この例では、doc1 行の 2 と doc2 行の 1 を使用して 2 つの行がソートされ、ソート結果は doc1 と doc2 になります。
    FieldSort fieldSort = new FieldSort("field1", SortOrder.DESC);
    fieldSort.setMode(SortMode.MIN);
}

Nested フィールドに対して mode パラメーターを指定して、子行のソートに使用する要素を決定することもできます。

// doc1 行と doc2 行には、Nested 型の field1 列が含まれています。
// doc1 行の field1 列の値は [{"name":"b", "age":1},{"name":"a", "age":7}] です。
// doc2 行の field1 列の値は [{"name":"a", "age":1},{"name":"c", "age":1},{"name":"d", "age":5}] です。

{
    // mode パラメーターを指定して、子行をソートするために使用される 2 つの行の Nested フィールドの要素を決定できます。
    // mode パラメーターを SortMode.MAX に設定すると、Nested フィールドの最大要素を使用して行がソートされます。 この例では、doc1 行の 7 と doc2 行の 5 を使用して、age 列で 2 つの行がソートされ、ソート結果は doc1 と doc2 になります。
    FieldSort fieldSort = new FieldSort("field1.age", SortOrder.DESC);
    fieldSort.setMode(SortMode.MAX);
    String path = "field1";
    NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.matchAll().build());
    fieldSort.setNestedFilter(nestedFilter);
}
{
    // mode パラメーターを指定して、age 列の値が 1 である子行をソートするために使用される 2 つの行の Nested フィールドの要素を決定できます。
    {
        // mode パラメーターを SortMode.MAX に設定すると、Nested フィールドの最大要素を使用して行がソートされます。 この例では、doc1 行の "b" と doc2 行の "a" を使用して、name 列で 2 つの行がソートされ、ソート結果は doc2 と doc1 になります。
        FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
        fieldSort.setMode(SortMode.MAX);
        String path = "field1";
        NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("students.age",1).build());
        fieldSort.setNestedFilter(nestedFilter);
    }
    {
        // mode パラメーターを SortMode.MIN に設定すると、Nested フィールドの最小要素を使用して行がソートされます。 この例では、doc1 行の "b" と doc2 行の "a" を使用して、name 列で 2 つの行がソートされ、ソート結果は doc1 と doc2 になります。
        FieldSort fieldSort = new FieldSort("field1.name", SortOrder.DESC);
        fieldSort.setMode(SortMode.MIN);
        String path = "field1";
        NestedFilter nestedFilter = new NestedFilter(path, QueryBuilders.term("students.age",1).build());
        fieldSort.setNestedFilter(nestedFilter);
    }
}

GeoDistanceSort

GeoDistanceSort を使用して、クエリ結果を地理的な場所に基づいてソートできます。

SearchQuery searchQuery = new SearchQuery();
// GEOPOINT geo列の値から座標ペア (0, 0) までの距離に基づいて結果をソートします。
Sort.Sorter sorter = new GeoDistanceSort("geo", Arrays.asList("0, 0"));
searchQuery.setSort(new Sort(Arrays.asList(sorter)));

ページング方法を指定する

レスポンスの行をページングするには、limit パラメーターと offset パラメーターを設定するか、トークンを使用します。

limit パラメーターと offset パラメーターを設定する

レスポンスの行の総数が 100,000 未満の場合、limit パラメーターと offset パラメーターを設定して行をページングできます。 limit パラメーターと offset パラメーターの値の合計は 100,000 を超えることはできません。 limit パラメーターの最大値は 100 です。

説明

limit パラメーターの最大値を増やす方法については、「検索インデックス機能の Search 操作を呼び出してデータをクエリするときに、limit パラメーターの値を 1000 に増やす方法」をご参照ください。

limit パラメーターと offset パラメーターの値を指定しない場合、デフォルト値が使用されます。 limit パラメーターのデフォルト値は 10 です。 offset パラメーターのデフォルト値は 0 です。

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

トークンを使用する

この方法ではページングの深さに制限がないため、ディープページングにはトークンを使用することをお勧めします。

クエリ条件を満たすすべてのデータを読み取れない場合、Tablestore は nextToken を返します。 nextToken を使用して、後続のデータの読み取りを続行できます。

デフォルトでは、トークンを使用する場合、後方へのページングのみ可能です。ただし、トークンはクエリ中は有効であるため、前のトークンをキャッシュして使用することで前方へページングできます。

重要

nextToken を永続化する場合、または nextToken をフロントエンド ページに転送する場合は、Base64 を使用して nextToken を文字列にエンコードできます。トークンは文字列ではありません。 new String(nextToken) を使用してトークンを文字列にエンコードすると、トークンに関する情報が失われます。

トークンを使用する場合、ソート方法は前のリクエストで使用された方法と同じです。 Tablestore は、デフォルトで IndexSort パラメーターに基づいて、または指定した方法に基づいてデータをソートします。トークンを使用する場合、ソート方法を指定することはできません。トークンを使用する場合、offset パラメーターを設定することはできません。データはページごとに順番に返されます。このため、スロークエリが発生します。

重要

Nested フィールドを含む検索インデックスは、IndexSort をサポートしていません。ページングが必要で、Nested フィールドを含む検索インデックスを使用してデータをクエリする場合は、クエリ条件でソート方法を指定して、指定した順序でデータを返す必要があります。そうしないと、クエリ条件を満たすデータの一部のみが返された場合、Tablestore は nextToken を返しません。

private static void readMoreRowsWithToken(SyncClient client) {
    SearchQuery searchQuery = new SearchQuery();
    searchQuery.setQuery(new MatchAllQuery());
    searchQuery.setGetTotalCount(true);// クエリ条件を満たす行の総数が返されるように指定します。
    // データテーブルの名前を指定します。例:sampleTable。次に、検索インデックスの名前を指定します。例:sampleSearchIndex。検索インデックス名を取得するには、Tablestore コンソールまたは Tablestore SDK を使用して検索インデックスのリストをクエリします。 Tablestore コンソールで検索インデックスのリストをクエリする場合は、「テーブルの管理」ページの「インデックス」タブでリストを表示できます。
    SearchRequest searchRequest = new SearchRequest("sampleTable", "sampleSearchIndex", searchQuery);

    SearchResponse resp = client.search(searchRequest);
    if (!resp.isAllSuccess()) {
        throw new RuntimeException("not all success");
    }
    List<Row> rows = resp.getRows();
    while (resp.getNextToken()!=null) { // レスポンスの nextToken 値が null の場合、すべてのデータが読み取られます。
        // nextToken 値をクエリします。
        byte[] nextToken = resp.getNextToken();

        {
            // nextToken を永続化する場合、または nextToken をフロントエンド ページに転送する場合は、Base64 を使用して nextToken を文字列にエンコードできます。
            // トークンは文字列ではありません。 new String(nextToken) を使用してトークンを文字列にエンコードすると、トークンに関する情報が失われます。
            String tokenAsString = Base64.toBase64String(nextToken);
            // 文字列をバイトにデコードします。
            byte[] tokenAsByte = Base64.fromBase64String(tokenAsString);
        }

        // このリクエストのトークンを前のレスポンスの nextToken 値に設定します。
        searchRequest.getSearchQuery().setToken(nextToken);
        resp = client.search(searchRequest);
        if (!resp.isAllSuccess()) {
            throw new RuntimeException("not all success");
        }
        rows.addAll(resp.getRows());
    }
    System.out.println("RowSize: " + rows.size());
    System.out.println("TotalCount: " + resp.getTotalCount());// 返された行数ではなく、クエリ条件を満たす行の総数が表示されるように指定します。
}