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

Tablestore:ソートとページング

最終更新日:Apr 30, 2026

多次元インデックスを使用してデータをクエリする際、事前に定義されたソート順を使用することも、クエリ時にソート方法を指定することもできます。大規模な結果セットをナビゲートするには、オフセットベースのページングに limit/offset を使用するか、カーソルベースのページングにトークンを使用します。

利用シーン

カテゴリ

メソッド

機能

シナリオ

ソート

多次元インデックス作成時にソート方法を事前定義する

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

デフォルトでは、インデックス作成時に IndexSort パラメーターで定義された順序で結果が返されます。

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

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

BM25 関連スコアに基づいて結果をソートします。全文検索に最適です。

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

プライマリキー値に基づいて結果をソートします。一意の行識別子で結果を並べ替える必要がある場合に便利です。

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

販売数量やページビューなどのカラム値に基づいて結果をソートします。EC サイト、SNS、メディアアセット管理などでよく使用されます。

地理的位置に基づくソート (GeoDistanceSort)

中心点からの距離に基づいて結果をソートします。地図サービスや物流などでよく使用されます(例:近隣のレストランを距離順に並べ替える)。

ページング

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

limit および offset パラメーターに基づくページング

結果セットの行数が 100,000 行未満の場合、任意のページにジャンプできます。

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

カーソルを使用して結果を順次ページングします。前方へのみページング可能です。トークンはクエリの持続時間中有効であるため、以前のトークンをキャッシュして前のページに戻ることができます。

インデックス事前ソート

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

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

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

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

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

ソート方法の指定

ソートを行うには、ソート対象のフィールドに対して enableSortAndAggtrue に設定する必要があります。

各クエリごとにソート方法を指定できます。多次元インデックスベースのクエリでは、以下のソート方法がサポートされています。また、異なる優先度に基づいて複数のソート方法を指定することもできます。

ScoreSort

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

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

  • ScoreSort を使用する場合、FuzzyKeyword 型のフィールドはソートに使用されず、そのフィールドに対する重みパラメーターの設定は効果がありません。

ScoreSort を使用して、BM25 関連スコアに基づき昇順または降順で結果をランク付けします。

sort: {
    sorters: [
        {
            scoreSort: {
                order: TableStore.SortOrder.SORT_ORDER_ASC
            }
        }
    ]
}

PrimaryKeySort

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

PrimaryKeySort を使用して、プライマリキー値で結果を並べ替えます。

sort: {
    sorters: [
        {
            primaryKeySort: {
                order: TableStore.SortOrder.SORT_ORDER_DESC // 降順でソートします。
                //order: TableStore.SortOrder.SORT_ORDER_ASC // 昇順でソートします。
            }
        }
    ]
}

FieldSort

FieldSort を使用して、1 つ以上のカラム値に基づいて結果をソートします。

単一カラムによるソート

sort: {
    sorters: [
        {
            fieldSort: {
                fieldName: "Col_Keyword",
                order: TableStore.SortOrder.SORT_ORDER_DESC
            }
        }
    ]
}

複数カラムによるソート

複数のソーターを指定して、まず主カラムでソートし、その後副カラムで同順位を解消します。

sort: {
    sorters: [
        {
            fieldSort: {
                fieldName: "Col_Keyword",
                order: TableStore.SortOrder.SORT_ORDER_DESC
            }
        },
        {
            fieldSort: {
                fieldName: "Col_Long",
                order: TableStore.SortOrder.SORT_ORDER_DESC
            }
        }
    ]
}

GeoDistanceSort

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

GeoDistanceSort を使用して、中心となる地理的ポイントからの距離に基づき結果をランク付けします。

sort: {
    sorters: [
        {
            geoDistanceSort: {
                fieldName: "Col_Geo_Point",
                points: ["0,0"],// 中心点の座標ペアを指定します。
                order: TableStore.SortOrder.SORT_ORDER_ASC // 距離の昇順で結果を返します。
            }
        }
    ]
}

完全なサンプルについては、GitHub の「Search」をご参照ください。

ページング方法の指定

応答内の行をページングするために、limit および offset パラメーターを設定するか、トークンを使用できます。

limit および offset パラメーターの設定

応答の総行数が 100,000 行未満の場合、limit および offset パラメーターを設定して行をページングできます。limit および offset パラメーターの値の合計は 100,000 を超えてはなりません。limit パラメーターの最大値は 100 です。

説明

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

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

offset および limit を使用して、任意のページに直接ジャンプします。この方法は最大 100,000 行の結果セットをサポートします。

/**
 * offset を 90、limit を 10 に設定して、90~99 行目を取得します。
 */
client.search({
    tableName: TABLE_NAME,
    indexName: INDEX_NAME,
    searchQuery: {
        offset: 90,
        limit: 10,
        query: {
            queryType: TableStore.QueryType.MATCH_ALL_QUERY
        },
        getTotalCount: true // 一致する行の総数を返します。デフォルト: false。
    },
    columnToGet: {
        // RETURN_ALL: すべてのカラムを返します。
        // RETURN_SPECIFIED: 指定されたカラムを返します。
        // RETURN_NONE: プライマリキーカラムのみを返します。
        returnType: TableStore.ColumnReturnType.RETURN_ALL
    }
}, function (err, data) {
    if (err) {
        console.log('error:', err);
        return;
    }
    console.log('success:', JSON.stringify(data, null, 2));
});

トークンの使用

深さのあるページングには、ページング深度に制限がないため、トークンの使用を推奨します。

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

デフォルトでは、トークンを使用する場合、前に戻ることしかできません。ただし、トークンはクエリ中に有効であるため、前のトークンをキャッシュして使用することで次に進むことができます。

トークンベースのページングは、カーソル (NextToken) を使用して結果をページごとに返します。各応答には次のページ用のトークンが含まれます。トークンはクエリの持続時間中に有効であるため、以前のトークンをキャッシュして前のページに戻ることができます。

重要

NextToken を永続化するかフロントエンドページに渡すには、Base64 文字列としてエンコードしてください。トークンは文字列ではなくバイナリデータ(バイトストリーム)です。string(NextToken) を使用するとデータが失われます。Buffer を使用して変換してください。

  1. エンコード: data.nextToken.toString("base64")

  2. デコード: Buffer.from(base64String, "base64")

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

重要

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

以下の例は、同期モードと非同期モードの両方におけるトークンベースのページングを示しています。どちらも同じ初期 params オブジェクトを使用します。

var params = {
    tableName: TABLE_NAME,
    indexName: INDEX_NAME,
    searchQuery: {
        offset: 0,
        limit: 10,
        token: null, // 次のページを取得するには、前回の応答の nextToken を設定します。
        query: {
            queryType: TableStore.QueryType.MATCH_ALL_QUERY
        },
        getTotalCount: true
    },
    columnToGet: {
        returnType: TableStore.ColumnReturnType.RETURN_SPECIFIED,
        returnNames: ["pic_tag", "pic_description", "time_stemp", "pos"]
    }
};

/**
 * 同期モード: 次のページを取得する前に各ページを await します。
 */
(async () => {
  try {
    var data = await client.search(params);
    console.log('success:', JSON.stringify(data, null, 2));

    while (data.nextToken && data.nextToken.length) {
      // バイナリトークンを Base64 としてエンコードして保存または転送し、
      // 次のトークンとして渡す前にバイナリに戻します。
      var nextToken = data.nextToken.toString("base64");
      var token = Buffer.from(nextToken, "base64");

      params.searchQuery.token = token;
      data = await client.search(params);
      console.log('token success:', JSON.stringify(data, null, 2));
    }
  } catch (error) {
      console.log(error);
  }
})()

/**
 * 非同期モード: コールバックを使用して次のページを取得します。
 */
client.search(params, function (err, data) {
    console.log('success:', JSON.stringify(data, null, 2));

    if (data.nextToken && data.nextToken.length) {
        // 同期モードと同様にトークンをエンコードおよびデコードします。
        var nextToken = data.nextToken.toString("base64");
        var token = Buffer.from(nextToken, "base64");

        params.searchQuery.token = token;
        client.search(params, function (err, data) {
            console.log('token success:', JSON.stringify(data, null, 2));
        });
    }
});