項目と属性の操作 - Amazon DynamoDB

項目と属性の操作

Amazon DynamoDB では、項目は属性の集まりです。各属性には名前と値があります。属性値はスカラー型、セット型、ドキュメント型のいずれかです。詳細については、「Amazon DynamoDB: 仕組み」を参照してください。

DynamoDB では、作成、読み込み、更新、および削除 (CRUD) の 4 つの基本的な操作機能を使用できます。これらの操作はすべてアトミックです。

  • PutItem — 項目を作成します。

  • GetItem — 項目を読み込みます。

  • UpdateItem — 項目を更新します。

  • DeleteItem — 項目を削除します。

これらの各オペレーションでは、作業対象の項目のプライマリキーを指定する必要があります。たとえば、GetItem を使用して項目を読み込むには、その項目のパーティションキーとソートキー (該当する場合) を指定する必要があります。

4 つの基本的な CRUD オペレーションに加えて、DynamoDB は以下も提供します。

  • BatchGetItem — 1 つ以上のテーブルから最大 100 個の項目を読み込みます。

  • BatchWriteItem — 1 つ以上のテーブルから最大 25 個の項目を作成または削除します。

これらのバッチ操作は、複数の CRUD オペレーションを単一のリクエストにまとめます。さらに、応答のレイテンシーを最小限に抑えるため、バッチオペレーションは項目を並列で読み書きします。

このセクションには、これらのオペレーションを使用する方法の説明、および、条件付き更新やアトミックカウンターなどの関連するトピックが含まれています。このセクションには、AWS SDK を使用するサンプルコードも含まれています。

項目の読み込み

DynamoDB テーブルから項目を読み込むには、GetItem オペレーションを使用します。必要な項目のプライマリキーと共にテーブルの名前を指定する必要があります。

次の AWS CLI の例は、ProductCatalog テーブルから項目を読み込む方法を示しています。

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}'
注記

GetItem では、プライマリキーの一部だけではなく全体を指定する必要があります。たとえば、テーブルに複合プライマリキー (パーティションキーおよびソートキー) がある場合、パーティションキーおよびソートキーの値を指定する必要があります。

デフォルトでは、GetItem リクエストは結果的に整合性のある読み込みを行います。代わりに、ConsistentRead パラメータを使用して、強い整合性のある読み込みをリクエストできます。(これは、追加の読み込みキャパシティーユニットを消費しますが、項目の最新バージョンを返します)。

GetItem は、項目のすべての属性を返します。一部の属性のみが返されるように、プロジェクション式を使用できます。詳細については、「プロジェクション式」を参照してください。

GetItem で消費される読み込みキャパシティーユニットの数を返すには、ReturnConsumedCapacity パラメータを TOTAL に設定します。

次の AWS Command Line Interface (AWS CLI) の例は、オプションの GetItem パラメータを示しています。

aws dynamodb get-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --consistent-read \ --projection-expression "Description, Price, RelatedItems" \ --return-consumed-capacity TOTAL

項目を書き込みます

DynamoDB テーブルの項目を作成、更新、または削除するには、次のオペレーションのいずれかを使用します。

  • PutItem

  • UpdateItem

  • DeleteItem

これらの各オペレーションで、プライマリキーの一部の属性ではなくすべての属性を指定する必要があります。たとえば、テーブルに複合プライマリキー (パーティションキーおよびソートキー) がある場合、パーティションキーおよびソートキーの値を提供する必要があります。

これらのオペレーションのいずれかで消費される書き込みキャパシティーユニットの数を返すには、ReturnConsumedCapacity パラメータを次のいずれかに設定します。

  • TOTAL — 消費された書き込み容量単位の総数を返します。

  • INDEXES — 消費された書き込み容量単位の総数とともに、テーブルおよびオペレーションに影響を受けたセカンダリインデックスの小計を返します。

  • NONE — 書き込み容量の詳細は返されません。(これがデフォルトです)

PutItem

PutItem は新しい項目を作成します。同じキーを持つ項目がテーブルにすでに存在する場合は、新しい項目に置き換えられます。

Thread テーブルに新しい項目を書き込みます。Thread のプライマリキーは、ForumName (パーティションキー) と Subject (ソートキー) で構成されます。

aws dynamodb put-item \ --table-name Thread \ --item file://item.json

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

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"}, "Message": {"S": "First post in this thread"}, "LastPostedBy": {"S": "fred@example.com"}, "LastPostDateTime": {"S": "201603190422"} }

UpdateItem

指定されたキーを持つ項目が存在しない場合は、UpdateItem により新しい項目が作成されます。または、既存の項目の属性が変更されます。

更新式を使用して、変更する属性と新しい値を指定します。詳細については、「更新式」を参照してください。

更新式では、実際の値にプレースホルダーとして式の属性値を使用します。詳細については、「式の属性値」を参照してください。

Thread 項目のさまざまな属性を変更します。オプションの ReturnValues パラメータは、更新後に表示されるように項目を表示します。詳細については、「戻り値」を参照してください。

aws dynamodb update-item \ --table-name Thread \ --key file://key.json \ --update-expression "SET Answered = :zero, Replies = :zero, LastPostedBy = :lastpostedby" \ --expression-attribute-values file://expression-attribute-values.json \ --return-values ALL_NEW

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

{ "ForumName": {"S": "Amazon DynamoDB"}, "Subject": {"S": "New discussion thread"} }

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

{ ":zero": {"N":"0"}, ":lastpostedby": {"S":"barney@example.com"} }

DeleteItem

DeleteItem は指定されたキーを持つ項目を削除します。

次の AWS CLI の例で、Thread 項目を削除する方法について説明します。

aws dynamodb delete-item \ --table-name Thread \ --key file://key.json

戻り値

場合によっては、ある属性値を変更する前後にその属性値が表示されるように DynamoDB で返すこともできます。PutItemUpdateItem、および DeleteItem オペレーションには、ReturnValues パラメータがあり、これを使用することで、属性の変更前後に、その属性値を返すことができます。

ReturnValues のデフォルトの値は NONE で、DynamoDB は変更された属性の情報を返しません。

以下は、DynamoDB API オペレーションごとに整理された ReturnValues のその他の有効な設定です。

PutItem

  • ReturnValues: ALL_OLD

    • 既存の項目に上書きする場合、ALL_OLD は上書きの前に表示されたように、項目全体を返します。

    • 存在しない項目を書き込んだ場合は、ALL_OLD による影響はありません。

UpdateItem

UpdateItem の最も一般的な使用方法は、既存の項目の更新です。ただし、UpdateItem は実際にはアップサートを実行します。つまり、項目が存在しない場合は、自動的に作成します。

  • ReturnValues: ALL_OLD

    • 既存の項目を更新する場合、ALL_OLD は更新前に表示されたように、項目全体を返します。

    • 存在しない項目を更新 (アップサート) すると、ALL_OLD による影響はありません。

  • ReturnValues: ALL_NEW

    • 既存の項目を更新する場合、ALL_NEW は更新後に表示されるように、項目全体が返されます。

    • 存在しない項目を更新 (アップサート) すると、ALL_NEW は項目全体を返します。

  • ReturnValues: UPDATED_OLD

    • 既存の項目を更新した場合、UPDATED_OLD は、更新前に表示されたように、更新された属性だけを返します。

    • 存在しない項目を更新 (アップサート) すると、UPDATED_OLD による影響はありません。

  • ReturnValues: UPDATED_NEW

    • 既存の項目を更新した場合、UPDATED_NEW は、更新後に表示されるように、影響のある属性だけを返します。

    • 存在しない項目を更新 (アップサート) する場合、UPDATED_NEW は更新後に表示される、更新された属性だけを返します。

DeleteItem

  • ReturnValues: ALL_OLD

    • 既存の項目を削除すると、ALL_OLD は削除の前に表示されたように、項目全体を返します。

    • 存在しない項目を削除すると、ALL_OLD はデータを返しません。

バッチオペレーション

複数の項目の読み込みや書き込みを必要とするアプリケーションのために、DynamoDB は BatchGetItem および BatchWriteItem オペレーションを提供します。これらのオペレーションを使用すると、アプリケーションから DynamoDB へのネットワークラウンドトリップの数を減らすことができます。さらに、DynamoDB は個別の読み込みまたは書き込みオペレーションを並行して実行します。同時実行またはスレッディングの管理をする必要がないので、アプリケーションにはこの並列処理が役立ちます。

バッチオペレーションは、基本的に複数の読み込みまたは書き込みリクエストをまとめます。たとえば、BatchGetItem リクエストに 5 つの項目が含まれている場合、DynamoDB によって 5 回の GetItem オペレーションが実行されます。同様に、BatchWriteItem リクエストに 2 つの PUT リクエストと 4 つの DELETE リクエストが含まれている場合、DynamoDB によって 2 つの PutItem リクエストと 4 つの DeleteItem リクエストが実行されます。

一般的に、バッチのすべてのリクエストが失敗しない限り、バッチオペレーションは失敗しません。たとえば、BatchGetItem オペレーションを実行する際、バッチの個々の GetItem リクエストが失敗したとします。この場合、BatchGetItem は失敗した GetItem リクエストからキーとデータを返します。バッチのその他の GetItem リクエストは影響を受けません。

BatchGetItem

1 回の BatchGetItem オペレーションには、最大 100 の個々の GetItem リクエストが含まれていて、最大 16 MB のデータを取得できます。さらに、BatchGetItem オペレーションで、複数のテーブルから項目を取得できます。

一部の属性のみが返されるようにプロジェクション式を使用して Thread テーブルから 2 つの項目を取得します。

aws dynamodb batch-get-item \ --request-items file://request-items.json

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

{ "Thread": { "Keys": [ { "ForumName":{"S": "Amazon DynamoDB"}, "Subject":{"S": "DynamoDB Thread 1"} }, { "ForumName":{"S": "Amazon S3"}, "Subject":{"S": "S3 Thread 1"} } ], "ProjectionExpression":"ForumName, Subject, LastPostedDateTime, Replies" } }

BatchWriteItem

BatchWriteItem オペレーションには最大 25 の個々の PutItem リクエストと DeleteItem リクエストを含むことができ、最大 16 MB のデータを書き込めます。(個々の項目の最大サイズは 400 KB です。) さらに、BatchWriteItem オペレーションで、複数のテーブルの項目を入力したり削除したりできます。

注記

BatchWriteItem では UpdateItem リクエストはサポートされません。

ProductCatalog テーブルに 2 つの項目を書き込みます。

aws dynamodb batch-write-item \ --request-items file://request-items.json

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

{ "ProductCatalog": [ { "PutRequest": { "Item": { "Id": { "N": "601" }, "Description": { "S": "Snowboard" }, "QuantityOnHand": { "N": "5" }, "Price": { "N": "100" } } } }, { "PutRequest": { "Item": { "Id": { "N": "602" }, "Description": { "S": "Snow shovel" } } } } ] }

アトミックカウンタ

この UpdateItem オペレーションを使用して、アトミックカウンター (他の書き込みリクエストに干渉することなく無条件に増分される数値属性) を実装できます。(すべての書き込みリクエストは、受信された順に適用されます)。アトミックカウンターでは、更新はべき等ではありません。つまり、UpdateItem を呼び出すたびに数値はインクリメントまたはデクリメントされます。アトミックカウンタの更新に使用されるインクリメント値が正の場合、オーバーカウントが発生する可能性があります。インクリメント値が負の場合、アンダーカウントの原因となります。

ウェブサイトの訪問者数を追跡するためにアトミックカウンターを使用できます。この場合、アプリケーションでは、現在値に関係なく、数値はインクリメントされます。UpdateItem オペレーションが失敗した場合、アプリケーションはオペレーションを再試行します。これには、カウンターを 2 度更新する恐れがありますが、ウェブサイトの訪問者数のカウントに多少の誤差があっても許容できるでしょう。

アトミックカウンターはカウントの誤差が許容されない場合にはふさわしくありません (銀行業務用のアプリケーションなど)。この場合は、アトミックカウンターの代わりに条件付き更新を使用する方が安全です。

詳細については、「数値属性の増減」を参照してください。

次の AWS CLI の例では、商品の Price が 5 でインクリメントされます。この例では、カウンタが更新される前に項目が存在することがわかっていました。(UpdateItem は冪等性ではないので、Price はこのコードを実行するたびに増えていきます)。

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id": { "N": "601" }}' \ --update-expression "SET Price = Price + :incr" \ --expression-attribute-values '{":incr":{"N":"5"}}' \ --return-values UPDATED_NEW

条件付きの書き込み

デフォルトでは、DynamoDB 書き込みオペレーション (PutItemUpdateItemDeleteItem) は無条件です。つまり、これらの各オペレーションでは、指定されたプライマリキーを持つ既存の項目が上書きされます。

DynamoDB はオプションでこれらのオペレーションの条件付き書き込みをサポートしています。条件付き書き込みが成功するのは、項目の属性が 1 つ以上の想定条件を満たす場合のみです。それ以外の場合は、エラーが返されます。

条件付き書き込みでは、その条件について項目の最新更新バージョンと照合します。なお、項目が以前に存在しなかった場合や、その項目に対して最後に成功した操作が削除であった場合、条件付き書き込みでは以前の項目は検出されません。

条件付き書き込みは多くの状況で役立ちます。たとえば、同じプライマリキーを持つ既存の項目がない場合にのみ、PutItem オペレーションが成功するようにできます。または、属性の 1 つに特定の値がある場合に UpdateItem オペレーションが項目を変更することを防ぐことができます。

条件付き書き込みは、複数のユーザーが同じ項目を変更しようとする場合に役立ちます。2 人のユーザー (Alice と Bob) が DynamoDB テーブルから同じ項目を処理している以下の図を考慮します。

Alice と Bob は、ID 1 の項目を変更しようとし、条件付き書き込みの必要性を示します。

Alice が AWS CLI を使用して Price 属性を 8 に更新するとします。

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --expression-attribute-values file://expression-attribute-values.json

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

{ ":newval":{"N":"8"} }

次に、Bob が後で同様の UpdateItem リクエストを発行しますが、Price を 12 に変更します。Bob には、--expression-attribute-values パラメータは次のように見えます。

{ ":newval":{"N":"12"} }

Bob のリクエストは成功しますが、その前の Alice の更新は失われます。

条件付き PutItemDeleteItem、または UpdateItem をリクエストするには、条件式を指定します。条件式は、属性名、条件付き演算子および組み込み関数を含む文字列です。式全体の評価が true になる必要があります。それ以外の場合は、このオペレーションは失敗します。

次は、条件付き書き込みにより Alice の更新が上書きされるのを防ぐ方法について、以下の図を考慮します。

条件付き書き込みにより、ユーザー Bob の更新によってユーザー Alice の変更が同じ項目に上書きされるのを防ぐことができます。

Alice はまず Price を 8 に更新を試行しますが、現在の Price が 10 である場合にのみ、という条件でそうします。

aws dynamodb update-item \ --table-name ProductCatalog \ --key '{"Id":{"N":"1"}}' \ --update-expression "SET Price = :newval" \ --condition-expression "Price = :currval" \ --expression-attribute-values file://expression-attribute-values.json

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

{ ":newval":{"N":"8"}, ":currval":{"N":"10"} }

条件が true に評価されるため、Alice の更新は成功します。

次に、Bob は、Price を 12 に 更新しますが、現在の Price が 10 である場合にのみ、という条件でそうします。Bob には、--expression-attribute-values パラメータは次のように見えます。

{ ":newval":{"N":"12"}, ":currval":{"N":"10"} }

Alice がすでに Price を 8 に変更していたので、条件式は false 評価され Bob の更新は失敗します。

詳細については、「条件式」を参照してください。

条件付き書き込みの冪等性

条件付き書き込みは、条件チェックが更新される同じ属性で行われる場合に、べき等性が保たれます。つまり、リクエスト時に項目の特定の属性値が想定されたものである場合にのみ、DynamoDB によって指定された書き込みリクエストが実行されます。

たとえば、UpdateItem リクエストを発行し、項目の Price を、現在の Price が 20 である場合のみ、3 増加させるとします。リクエストを送信した後、その結果を得る前にネットワークエラーが発生したため、リクエストが成功したかどうか不明です。この条件付き書き込みはべき等のオペレーションであるため、同じ UpdateItem リクエストを再試行できます。すると、DynamoDB は、現在の Price が 20 である場合のみ項目を更新します。

条件付き書き込みで消費されるキャパシティユニット

条件付き書き込み中に ConditionExpression が false と評価された場合でも、DynamoDB はテーブルの書き込みキャパシティを消費します。消費量は、既存の項目のサイズ(または最低 1)によって異なります。例えば、既存の項目が 300 KB で、作成または更新しようとしている新しい項目が 310 KB の場合、消費される書き込みキャパシティーユニットは、条件が満たされないかったら 300、満たされたら 310 になります。これが新しい項目 (既存の項目なし) の場合、消費される書き込みキャパシティーユニットは条件が満たされれば 1、条件が満たされなかったら 310 になります。

注記

書き込みオペレーションでは、書き込みキャパシティユニットのみが消費されます。読み込みキャパシティユニットが消費されることはありません。

失敗した条件付き書き込みは ConditionalCheckFailedException を返します。これが起きると、消費された書き込みキャパシティに関する情報はレスポンスで返されません。

条件付き書き込みの際に消費された書き込みキャパシティーユニットの数を返すには、ReturnConsumedCapacity パラメータを使用します。

  • TOTAL — 消費された書き込み容量単位の総数を返します。

  • INDEXES — 消費された書き込み容量単位の総数とともに、テーブルおよびオペレーションに影響を受けたセカンダリインデックスの小計を返します。

  • NONE — 書き込み容量の詳細は返されません。(これがデフォルトです)

注記

グローバルセカンダリインデックスとは異なり、ローカルセカンダリインデックスは、プロビジョンドスループット性能をそのテーブルと共有します。ローカルセカンダリインデックスでの読み込みと書き込みのアクティビティは、テーブルからプロビジョンドスループット性能を消費します。