

# DynamoDB でテーブルクエリ結果をページ分割する
<a name="Query.Pagination"></a>

DynamoDB では、`Query` オペレーションの結果を*ページ割り*します。ページ分割を行うことで `Query` 結果が 1 MB サイズ (またはそれ以下) のデータの「ページ」に分割されます。アプリケーションは結果の最初のページ、次に 2 ページと処理できます。

1 つの `Query` は、サイズの制限である1 MB 以内の結果セットだけを返します。さらに結果があるかどうかを確認して、一度に 1 ページずつ結果を取り出すには、アプリケーションで次の操作を行う必要があります。

1. 低レベルの `Query` 結果を確認します。
   + 結果に `LastEvaluatedKey` 要素が含まれており、それが Null 以外の場合、ステップ 2 に進みます。
   + 結果に `LastEvaluatedKey` が*ない*場合、これ以上取得する項目はありません。

1. 同じ `KeyConditionExpression` を使用して `Query` を構築します。ただし、今回は、ステップ 1 から `LastEvaluatedKey` 値を取得して、新しい `Query` リクエストの `ExclusiveStartKey` パラメータとして使用します。

1. 新しい `Query` リクエストを実行します。

1. ステップ 1 に進んでください。

言い換えると、`Query` レスポンスからの `LastEvaluatedKey` を次の `Query` リクエストの `ExclusiveStartKey` として使用する必要があります。`Query` レスポンスに `LastEvaluatedKey` の要素がない場合、結果の最後のページを取得します。`LastEvaluatedKey` が空ではない場合でも、必ずしも結果セットにまだ値があることを意味するわけではありません。結果セットの最後まで到達したことを確認できるのは、`LastEvaluatedKey` が空になったときだけです。

AWS CLI を使用してこの動作を表示できます。AWS CLI は、`LastEvaluatedKey` が結果に表示されなくなるまで、低レベルの `Query` リクエストを DynamoDB に繰り返し送信します。特定の年の映画タイトルを取得する次の AWS CLI の例を考えてみます。

```
aws dynamodb query --table-name Movies \
    --projection-expression "title" \
    --key-condition-expression "#y = :yyyy" \
    --expression-attribute-names '{"#y":"year"}' \
    --expression-attribute-values '{":yyyy":{"N":"1993"}}' \
    --page-size 5 \
    --debug
```

通常、AWS CLI はページ分割を自動的に処理します。ただし、この例では、AWS CLI `--page-size` パラメータによりページごとの項目数が制限されています。`--debug` パラメータは、リクエストとレスポンスについての低レベルの情報を表示します。

この例を実行した場合、DynamoDB からの最初のレスポンスは次のようになります。

```
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":5,"Items":[{"title":{"S":"A Bronx Tale"}},
{"title":{"S":"A Perfect World"}},{"title":{"S":"Addams Family Values"}},
{"title":{"S":"Alive"}},{"title":{"S":"Benny & Joon"}}],
"LastEvaluatedKey":{"year":{"N":"1993"},"title":{"S":"Benny & Joon"}},
"ScannedCount":5}'
```

レスポンスの `LastEvaluatedKey` は、すべての項目が取得されたわけではないことを示します。その後、AWS CLI は DynamoDB に別の `Query` リクエストを送信します。このリクエストとレスポンスのパターンが、最終レスポンスまで繰り返されます。

```
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body:
b'{"Count":1,"Items":[{"title":{"S":"What\'s Eating Gilbert Grape"}}],"ScannedCount":1}'
```

`LastEvaluatedKey` がない場合、これ以上取得する項目がないことを示します。

**注記**  
AWS SDK は低レベルの DynamoDB レスポンス (`LastEvaluatedKey` の有無を含む) を処理し、ページ割りした `Query` 結果のさまざまな抽象化を提供します。たとえば、SDK for Java のドキュメントインターフェイスでは、`java.util.Iterator` サポートが利用可能なため、結果を一度に 1 つずつ確認できます。  
各種のプログラミング言語のコード例については、「[Amazon DynamoDB 利用開始ガイド](https://docs.aws.amazon.com/amazondynamodb/latest/gettingstartedguide/)」と、該当言語の「AWS SDK ドキュメント」を参照してください。

`Query` オペレーションの `Limit` パラメータを使用して結果セット内の項目数を制限することで、ページサイズを小さくすることもできます。

DynamoDB でのクエリ実行の詳細については、「[DynamoDB のテーブルに対するクエリの実行](Query.md)」を参照してください。