メニュー
Amazon DynamoDB
開発者ガイド (API Version 2012-08-10)

クエリの操作

Query オペレーションはプライマリキー値に基づいて項目を探します。複合プライマリキー (パーティションキーとソートキー) のあるテーブルまたは セカンダリインデックス をクエリできます。

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

キー条件式

検索条件を指定するには、テーブルまたはインデックスから読み込む項目を決める文字列であるキー条件式を使用します。等価条件としてパーティションキーの名前と値を指定する必要があります。オプションで、ソートキーに 2 番目の条件を指定できます (存在する場合)。ソートキーの条件では、次の比較演算子の 1 つを使用する必要があります。

  • a = b - 属性 a が値 b と等しい場合、true

  • a < b - ab より小さい場合、true

  • a <= b - ab 以下である場合、true

  • a > b - ab より大きい場合、true

  • a >= b - ab 以上である場合、true

  • a BETWEEN b AND c - ab 以上で、c 以下である場合、true。

次の関数もサポートされます。

  • begins_with (a, substr) - 属性の値 a が特定のサブ文字列から始まる場合、true。

キー条件式の使用方法を示す AWS CLI の例を次に示します。これらの式では、実際の値の代わりにプレースホルダー(:name:sub など)を使用しています。詳細については、「式の属性名」および「式の属性値」を参照してください。

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

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

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

Copy
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 に保存されます。

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

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

Copy
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 に保存されます。

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

最初の文字が a-z または A-Z であり、2 番目の文字(ある場合)が a-zA-Z、または 0-9 である場合は、キー条件式で任意の属性値を使用できます。さらに、属性名は DynamoDB の予約語ではない必要があります(フィールドの一覧については、「DynamoDB の予約語」を参照してください)。属性名がこれらの要件を満たさない場合は、式の属性名をプレースホルダーとして定義する必要があります。詳細については、「式の属性名」を参照してください。

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

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

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

1 回の Query オペレーションで、最大 1 MB のデータを取得できます。この制限は、結果への FilterExpression の適用前に適用されます。レスポンスに LastEvaluatedKey が存在し、Null 以外の場合、結果セットをページ分割する必要があります (ページ単位の出力件数を指定 を参照)。

クエリのフィルタ式

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

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

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

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

フィルタ式の構文は、条件式の構文と同じです。フィルタ式は、条件式と同じコンパレータ、関数および論理演算子を使用できます。詳細については, 条件式.

以下に、Thread テーブルで特定の ForumName (パーティションキー) および Subject (ソートキー) に対する AWS CLI のサンプルクエリを示します。見つかった項目のうち、最も一般的なディスカッションスレッドだけを返します (つまり、Views が特定の数を超えるスレッドだけ)。

Copy
aws dynamodb query \ --table-name Thread \ --key-condition-expression "ForumName = :fn" \ --filter-expression "#v >= :num" \ --expression-attribute-names '{"#v": "Views"}' \ --expression-attribute-values file://values.json

--expression-attribute-values の引数は、ファイル values.json に保存されます。

Copy
{ ":fn":{"S":"Amazon DynamoDB#DynamoDB Thread 1"}, ":num":{"N":"3"} }

Views は DynamoDB で予約語であるため (DynamoDB の予約語 を参照)、この例では #v をプレースホルダーとして使用します。詳細については、「式の属性名」を参照してください。

注記

フィルタ式は、Query 結果セットから項目を削除します。可能であれば、大量の項目を取得してもそのほとんどを破棄する必要のあるような Query を使用するのは避けます。

結果セットの項目数の制限

Query オペレーションは、結果で返される項目数を制限することができます。これを行うには、Limit パラメータに項目の最大数を設定します。

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

ここで、Query にフィルタ式を追加するとします。この場合、DynamoDB は返される 6 つの項目にフィルタ式を適用し、一致しない項目を廃棄します。最終的な Query 結果はフィルタリングされる項目の数に応じて、6 つ以下の項目を含みます。

ページ単位の出力件数を指定

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

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

  1. 低レベルの Query 結果を確認します。

    • 結果に LastEvaluatedKey 要素が含まれる場合、ステップ 2 に進みます。

    • 結果に LastEvaluatedKeyない場合、これ以上取得する項目はありません。

  2. 以前のものと同じパラメータを使用して新しい Query リクエストを作成します。今回は、ステップ 1 からの LastEvaluatedKey 値を取得して、新しい Query リクエストの ExclusiveStartKey パラメータとして使用します。

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

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

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

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

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

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

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

Copy
2017-07-07 11:13:15,603 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":5,"Items":[{"title":{"S":"Always"}},{"title":{"S":"Back to the Future Part II"}}, {"title":{"S":"Batman"}},{"title":{"S":"Bill & Ted\'s Excellent Adventure"}},{"title":{"S":"Black Rain"}}], "LastEvaluatedKey":{"year":{"N":"1989"},"title":{"S":"Black Rain"}}, "ScannedCount":5}

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

Copy
2017-07-07 11:13:16,291 - MainThread - botocore.parsers - DEBUG - Response body: b'{"Count":2,"Items":[{"title":{"S":"Uncle Buck"}},{"title":{"S":"Weekend at Bernie\'s"}}], "ScannedCount":2}'

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

注記

AWS SDK は低レベルの DynamoDB レスポンス (LastEvaluatedKey の存在または不在を含む) を処理し、ページ分割された Query 結果のさまざまな抽象化を提供します。たとえば、SDK for Java ドキュメントインターフェイスは java.util.Iterator サポートを提供するため、結果を一度に 1 つずつ確認できます。

各種のプログラミング言語のサンプルコードについては、『Amazon DynamoDB 入門ガイド』と、該当言語の AWS SDK ドキュメントを参照してください。

結果での項目のカウント

Query レスポンスには、条件に一致する項目に加えて次の要素が含まれます。

  • ScannedCount - フィルタ式 (存在する場合) が適用されるに、キー条件式に一致する項目数。

  • Count - フィルタ式 (存在する場合) が適用された、残っている項目数。

注記

フィルタ式を使用しない場合、ScannedCountCount は同じ値を持ちます。

Query 結果セットのサイズが 1 MB より大きい場合、ScannedCount および Count は、合計項目数の一部の数のみを表します。すべての結果を取得するためには、複数の Query オペレーションを実行する必要があります (ページ単位の出力件数を指定 を参照してください)。

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

クエリで消費されるキャパシティーユニット

複合プライマリキー (パーティションキーとソートキー) のある任意のテーブル、または提供される セカンダリインデックス で Query できます。Query オペレーションでは、次のように読み込みキャパシティーユニットを消費します。

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

デフォルトでは、Queryオペレーションはどのくらいの読み込みキャパシティーを消費するかについてのデータを返しません。ただし、この情報を取得するために Query リクエストで ReturnConsumedCapacityパラメータを指定できます。ReturnConsumedCapacity の有効な設定を以下に示します。

  • NONE - 消費されたキャパシティーデータは返されません。(これがデフォルトです)

  • TOTAL - レスポンスには消費された読み込みキャパシティーユニットの合計値が含まれます。

  • INDEXES - レスポンスは、アクセスする各テーブルとインデックスの消費されるキャパシティーとともに、消費される読み込みキャパシティーユニットの合計値を示します。

DynamoDB はアプリケーションに返されるデータ量ではなく、項目のサイズに基づいて、消費される読み込みキャパシティーユニットの数を計算します。このため、消費されるキャパシティーユニットの数は、(射影式を使用して) 属性のすべてをリクエストしても (デフォルトの動作) 一部をリクエストしても、同じになります。数は、フィルタ式を使用していてもいなくても同じです。

クエリの読み込み整合性

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

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