[解決済み] DynamoDB put-item ConditionalCheckFailedException
質問
以下のテーブルスキーマが定義されている場合(
create-table.json
を呼び出した後、次のようなエラーが発生します。
put-item
を使って
add-event1.json
に続いて
add-event2.json
:
PutItem オペレーションの呼び出し時に、クライアントエラー(ConditionalCheckFailedException)が発生しました。条件付きリクエストに失敗しました
なぜConditionExpressionでは両方のレコードを書き込めないのですか?(2回目の操作の後に2つのレコードがあることを期待しています)。
キー以外の条件を使用しているためではないかと疑いましたが、何も ドキュメント は、非キーコンディションをサポートしていないことを示すものです。
テーブルの作成
$ aws dynamodb create-table --cli-input-json file://create-table.json
create-table.json
{
"TableName": "EVENTS_TEST",
"KeySchema": [
{ "AttributeName": "aggregateId", "KeyType": "HASH" },
{ "AttributeName": "streamRevision", "KeyType": "RANGE" }
],
"AttributeDefinitions": [
{ "AttributeName": "aggregateId", "AttributeType": "S" },
{ "AttributeName": "streamRevision", "AttributeType": "N" }
],
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10
}
}
最初のレコードを追加する
$ aws dynamodb put-item --cli-input-json file://add-event1.json
追加イベント1.json
{
"TableName": "EVENTS_TEST",
"Item": {
"aggregateId": { "S": "id" },
"id": { "S": "119" },
"context": { "S": "*" },
"aggregate": { "S": "*" },
"streamRevision": { "N": "0" },
"commitId": { "S": "1119" },
"commitSequence": { "N": "0" },
"commitStamp": { "N": "1470185631511" },
"dispatched": { "BOOL": false },
"payload": { "S": "{ \"event\": \"bla\" }" }
},
"ExpressionAttributeNames": { "#name": "aggregate" },
"ConditionExpression": "attribute_not_exists(aggregateId) and attribute_not_exists(streamRevision) and #name <> :name and context <> :ctx",
"ExpressionAttributeValues": {
":name": { "S": "*" },
":ctx": { "S": "*" }
}
}
2つ目のレコードを追加する
$ aws dynamodb put-item --cli-input-json file://add-event2.json
追加イベント2.json
{
"TableName": "EVENTS_TEST",
"Item": {
"aggregateId": { "S": "id" },
"id": { "S": "123" },
"context": { "S": "myCtx" },
"aggregate": { "S": "myAgg" },
"streamRevision": { "N": "0" },
"commitId": { "S": "1123" },
"commitSequence": { "N": "0" },
"commitStamp": { "N": "1470185631551" },
"dispatched": { "BOOL": false },
"payload": { "S": "{ \"event\": \"bla2\" }" }
},
"ExpressionAttributeNames": { "#name": "aggregate" },
"ConditionExpression": "aggregateId <> :id and streamRevision <> :rev and #name <> :name and context <> :ctx",
"ExpressionAttributeValues": {
":id": { "S": "id" },
":rev": { "N": "0" },
":name": { "S": "myAgg" },
":ctx": { "S": "myCtx" }
}
}
解決方法は?
あなたの目標は、両方のレコードを保存することです。ここで2つの問題があります
- ハッシュとレンジキーの選択で、両方のレコードを保存することは不可能です。
ハッシュキーとレンジキーの組み合わせで、レコードは一意になります。 イベント1とイベント2は、ハッシュキーとレンジキーが同じ値になっています。 したがって、2番目のput-itemは最初のレコードを単純に上書きすることになります。
- あなたのConditionExpressionは、レコード1からレコード2への置き換えを防止します。
ConditionExpressionは、レコードを置く直前に評価されます。イベント2を挿入しようとしたときに、aggregateId "id1" を持つレコードがすでに存在することが判明したため、式は失敗します。この条件は "attribute_not_exists(aggregateId)" で失敗し、ConditionalCheckFailedException を受け取ります。 この式は、レコード2によるレコード1の上書きを防止します。
もし両方のレコードを保存したい場合は、データ項目の単一性をよりよく表すハッシュキーや範囲キーの別の選択を考え出す必要があります。ConditionExpression でそれを解決することはできません。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン