

# DynamoDB のテーブルに対するクエリの実行
<a name="Query"></a>

Amazon DynamoDB の `Query` オペレーションを使用して、プライマリキーの値に基づいて項目を探すことができます。

パーティションキーの属性名、および属性の単一値を指定する必要があります。`Query` はそのパーティションキー値を持つすべての項目を返します。必要に応じて、ソートキーの属性を指定し、比較演算子を使用して、検索結果をさらに絞り込むことができます。

リクエストの構文、レスポンスパラメータ、その他の例など、`Query` の使用方法の詳細については、*Amazon DynamoDB API リファレンス*の「[クエリ](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html)」を参照してください。

**Topics**
+ [DynamoDB でのクエリオペレーションのキー条件式](Query.KeyConditionExpressions.md)
+ [DynamoDB でのクエリオペレーションのフィルター式](Query.FilterExpression.md)
+ [DynamoDB でテーブルクエリ結果をページ分割する](Query.Pagination.md)
+ [DynamoDB でクエリオペレーションを使用する際のその他の側面](Query.Other.md)

# DynamoDB でのクエリオペレーションのキー条件式
<a name="Query.KeyConditionExpressions"></a>

最初の文字が `a-z` または `A-Z` であり、残りの文字 (ある場合、2 番目以降の文字) が `a-z`、`A-Z`、または `0-9` である場合は、キー条件式で任意の属性値を使用できます。さらに、属性名は DynamoDB の予約語であってはいけません。（詳細リストについては、「[DynamoDB の予約語](ReservedWords.md)」を参照してください） 属性名がこれらの要件を満たさない場合は、式の属性名をプレースホルダーとして定義する必要があります。詳細については、「[DynamoDB の式の属性名 (エイリアス)](Expressions.ExpressionAttributeNames.md)」を参照してください。

特定のパーティションキー値を持つ項目は、DynamoDB によってソートキーの値で並べ替えられた順序で近くに配置されて保存されます。`Query` オペレーションでは、並べ替えられた順序でDynamoDB によって項目が取得され、`KeyConditionExpression` や存在する任意の `FilterExpression` を使用して処理されます。その時初めて、`Query` の結果がクライアントに返されます。

`Query` オペレーションは常に結果セットを返します。一致する項目がない場合、結果セットは空になります。

`Query` の結果は常にソートキーの値によってソートされます。ソートキーのデータ型が `Number` である場合は、結果が番号順で返されます。その他の場合は、UTF-8 バイトの順序で結果が返されます。デフォルトの並べ替え順序は昇順です。順序を反転させるには、`ScanIndexForward` パラメータを `false` に設定します。

1 回の `Query` オペレーションで、最大 1 MB のデータを取得できます。この制限は、`FilterExpression` または `ProjectionExpression` が結果に適用される前に適用されます。レスポンスに `LastEvaluatedKey` が存在し、Null 以外の場合、結果セットをページ分割する必要があります ([DynamoDB でテーブルクエリ結果をページ分割する](Query.Pagination.md) を参照)。

## キー条件式の例
<a name="Query.KeyConditionExpressions-example"></a>

検索条件を指定するには、*キー条件式* (テーブルまたはインデックスから読み取る項目を決定する文字列) を使用します。

等価条件としてパーティションキーの名前と値を指定する必要があります。キー条件式では、非キー属性を使用することはできません。

オプションで、ソートキーに 2 番目の条件を指定できます (存在する場合)。ソートキーの条件では、次の比較演算子を 1 つ使用する必要があります。
+ `a = b` — 属性 *a* が値 *b* と等しい場合、true
+ `a < b` — *a* が *b* 未満の場合、true
+ `a <= b` — *a* が *b* 以下である場合、true
+ `a > b` — *a* が *b* より大きい場合、true
+ `a >= b` — *a* が *b* 以上である場合、true
+ `a BETWEEN b AND c` — *a* が *b* 以上で、*c* 以下である場合、true。

次の関数もサポートされます。
+ `begins_with (a, substr)` — 属性の値 `a` が特定のサブ文字列から始まる場合、true。

キー条件式の使用方法を示す AWS Command Line Interface (AWS CLI) の例を次に示します。これらの式では、実際の値の代わりにプレースホルダー (`:name` や `:sub` など) を使用しています。詳細については、「[DynamoDB の式の属性名 (エイリアス)](Expressions.ExpressionAttributeNames.md)」および「[DynamoDB での式属性値の使用](Expressions.ExpressionAttributeValues.md)」を参照してください。

**Example**  
`Thread` テーブルに対して、特定の `ForumName` (パーティションキー) についてのクエリを実行します。その `ForumName` の値を持つすべての項目はクエリによって読み込まれます。これはソートキー (`Subject`) が `KeyConditionExpression` に含まれないためです。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name" \
    --expression-attribute-values  '{":name":{"S":"Amazon DynamoDB"}}'
```

**Example**  
`Thread` テーブルに対して、特定の `ForumName` (パーティションキー) についてのクエリを実行しますが、今回は指定の `Subject` (ソートキー) を持つ項目のみを返します。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :name and Subject = :sub" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values` の引数は、`values.json` のファイルに保存されます。  

```
{
    ":name":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"}
}
```

**Example**  
`Reply` テーブルに対して、特定の `Id` (パーティションキー) についてのクエリを実行しますが、`ReplyDateTime` (ソートキー) が特定の文字で始まる項目のみを返します。  

```
aws dynamodb query \
    --table-name Reply \
    --key-condition-expression "Id = :id and begins_with(ReplyDateTime, :dt)" \
    --expression-attribute-values  file://values.json
```
`--expression-attribute-values` の引数は、`values.json` のファイルに保存されます。  

```
{
    ":id":{"S":"Amazon DynamoDB#DynamoDB Thread 1"},
    ":dt":{"S":"2015-09"}
}
```

# DynamoDB でのクエリオペレーションのフィルター式
<a name="Query.FilterExpression"></a>

`Query` 結果の絞り込みが必要な場合は、オプションでフィルタ式を指定できます。*フィルタ式*によって、`Query` 結果の内、どの項目を返すべきか確定します。他のすべての結果は破棄されます。

フィルタ式は、`Query` の完了後、結果が返される前に適用されます。そのため、`Query` は、フィルタ式があるかどうかにかかわらず、同じ量の読み込みキャパシティーを消費します。

1 回の `Query` オペレーションで、最大 1 MB のデータを取得できます。この制限は、フィルタ式を評価する前に適用されます。

フィルタ式には、パーティションキーまたはソートキーの属性を含めることはできません。フィルタ式ではなく、キー条件式でこれらの属性を指定する必要があります。

フィルター式の構文は、キー条件式の構文と似ています。フィルター式は、キー条件式と同じコンパレータ、関数および論理演算子を使用できます。さらに、フィルター式では、非等号演算子 (`<>`)、`OR` 演算子、`CONTAINS` 演算子、`IN` 演算子、`BEGINS_WITH` 演算子、`BETWEEN` 演算子、`EXISTS` 演算子、および `SIZE` 演算子を使用できます。詳細については、「[DynamoDB でのクエリオペレーションのキー条件式](Query.KeyConditionExpressions.md)」および「[フィルター式と条件式の構文](Expressions.OperatorsAndFunctions.md#Expressions.OperatorsAndFunctions.Syntax)」を参照してください。

**Example**  
以下の AWS CLI の例では、`Thread` テーブルに対して、特定の `ForumName` (パーティションキー) および `Subject` (ソートキー) についてのクエリを実行します。見つかった項目のうち、最も一般的なディスカッションスレッド (つまり、一定数以上の `Views` があるスレッド) のみが返されます。  

```
aws dynamodb query \
    --table-name Thread \
    --key-condition-expression "ForumName = :fn and Subject begins_with :sub" \
    --filter-expression "#v >= :num" \
    --expression-attribute-names '{"#v": "Views"}' \
    --expression-attribute-values file://values.json
```
`--expression-attribute-values` の引数は、`values.json` のファイルに保存されます。  

```
{
    ":fn":{"S":"Amazon DynamoDB"},
    ":sub":{"S":"DynamoDB Thread 1"},
    ":num":{"N":"3"}
}
```
`Views` は DynamoDB で予約語であるため ([DynamoDB の予約語](ReservedWords.md) を参照)、この例では `#v` をプレースホルダーとして使用することにご注意ください。詳細については、「[DynamoDB の式の属性名 (エイリアス)](Expressions.ExpressionAttributeNames.md)」を参照してください。

**注記**  
フィルタ式は、`Query` 結果セットから項目を削除します。可能であれば、大量の項目を取得してもそのほとんどを破棄する必要がある場合、 `Query` の使用は避けてください。

# 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)」を参照してください。

# DynamoDB でクエリオペレーションを使用する際のその他の側面
<a name="Query.Other"></a>

このセクションでは、DynamoDB クエリオペレーションのその他の側面について説明します。これには、結果サイズの制限、スキャンされた項目と返された項目のカウント、読み取り容量の消費のモニタリング、読み取り整合性の制御が含まれます。

## 結果セットの項目数の制限
<a name="Query.Limit"></a>

`Query` オペレーションを使用すると、読み取られる項目数を制限することができます。これを行うには、`Limit` パラメータに項目の最大数を設定します。

たとえば、フィルタ式を使用せず、`Limit` 値を `6` として、テーブルを `Query` するとします。`Query` 結果には、リクエストのキー条件式に一致するテーブルからの最初 6 つの項目が含まれます。

ここで、`Query` にフィルタ式を追加するとします。この場合、DynamoDB は最大 6 つの項目を読み込み、フィルタ式と一致する項目だけを返します。DynamoDB が項目の読み込みを続けた場合、さらに多くの項目がフィルタ式にマッチしても、最終的な `Query` 結果に含まれる項目数は 6 つ以下です。

## 結果での項目のカウント
<a name="Query.Count"></a>

`Query` レスポンスには、条件に一致する項目に加えて次の要素が含まれます。
+ `ScannedCount` — フィルター式 (存在する場合) が適用される*前に*、キー条件式に一致した項目数。
+ `Count` — フィルター式 (存在する場合) が適用された*後に*残っている項目数。

**注記**  
フィルタ式を使用しない場合、`ScannedCount` と `Count` は同じ値を持ちます。

`Query` 結果セットのサイズが 1 MB より大きい場合、`ScannedCount` および `Count` では、合計項目数の一部のみが示されます。すべての結果を取得するためには、複数の `Query` オペレーションを実行する必要があります ([DynamoDB でテーブルクエリ結果をページ分割する](Query.Pagination.md) を参照してください)。

各 `Query` レスポンスには、特定の `Query` リクエストによって処理された項目の `ScannedCount` および `Count` が含まれます。すべての `Query` リクエストの合計を取得するには、`ScannedCount` および `Count` の実行中の集計を維持することができます。

## クエリで消費されるキャパシティユニット
<a name="Query.CapacityUnits"></a>

パーティションキーの属性名、およびその属性の単一値を指定する限り、いずれのテーブルまたはセカンダリインデックスにも、`Query` を実行できます。`Query` により、そのパーティションのキー値を持つすべての項目が返されます。必要に応じて、ソートキーの属性を指定し、比較演算子を使用して、検索結果をさらに絞り込むことができます。`Query`API オペレーションでは、次のように読み込みキャパシティーユニットを消費します。


****  

| ...を `Query` する場合 | DynamoDB は ... からの読み込み容量ユニットを消費します。 | 
| --- | --- | 
| テーブル | テーブルのプロビジョニングされた読み込みキャパシティー。 | 
| グローバルセカンダリインデックス | インデックスのプロビジョニングされた読み込みキャパシティー。 | 
| ローカルセカンダリインデックス | ベーステーブルのプロビジョニングされた読み込みキャパシティー。 | 

デフォルトでは、`Query`オペレーションはどのくらいの読み込みキャパシティーを消費するかについてのデータを返しません。ただし、この情報を取得するために `Query` リクエストで `ReturnConsumedCapacity` パラメータを指定できます。`ReturnConsumedCapacity` の有効な設定を以下に示します。
+ `NONE` — 消費された容量データは返されません。(これがデフォルトです)
+ `TOTAL` — レスポンスには消費された読み込み容量単位の合計値が含まれます。
+ `INDEXES` — レスポンスは、アクセスする各テーブルとインデックスの消費される容量とともに、消費される読み込み容量単位の合計値を示します。

DynamoDB はアプリケーションに返されるデータ量ではなく、項目の数と項目のサイズに基づいて、消費される読み込みキャパシティユニットの数を計算します。このため、消費される容量ユニットの数は、(デフォルトの動作で) 属性のすべてをリクエストしても、(プロジェクション式を使用して) 一部をリクエストしても、同じになります。この数は、フィルター式を使用していてもいなくても同じです。`Query` は最小読み込みキャパシティユニットを消費して、最大 4 KB の項目について強力な整合性のある読み込みを 1 秒あたり 1 回、または結果整合性のある読み込みを 1 秒あたり 2 回実行します。4 KB より大きい項目を読み込む必要がある場合、DynamoDB には追加の読み込みリクエストユニットが必要です。空のテーブルや、パーティションキーの数が少ない非常に大きなテーブルでは、クエリされたデータの量を超えて追加の RCU が課金される場合があります。これにより、データが存在しない場合でも、`Query` リクエストを処理するためのコストがカバーされます。

## クエリの読み込み整合性
<a name="Query.ReadConsistency"></a>

`Query` オペレーションは、結果的に整合性のある読み込みをデフォルトで行います。つまり、`Query` 結果が、最近完了した `PutItem` または `UpdateItem` オペレーションによる変更を反映しない場合があります。詳細については、「[DynamoDB の読み取り整合性](HowItWorks.ReadConsistency.md)」を参照してください。

強力な整合性のある読み込みが必要な場合は、`Query` リクエストで `ConsistentRead` パラメータを `true` に設定します。