翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
条件式
PutItem、UpdateItem、および DeleteItem の各 DynamoDB 処理を使用して DynamoDB のオブジェクトをミューテーションする場合、オプションで、処理を実行する前に、DynamoDB にある既存のオブジェクトの状態に基づいてリクエストが成功するかどうかを制御する条件式を指定することができます。
AWS AppSync DynamoDB のリゾルバーを使用して、PutItem、UpdateItem、および DeleteItem の各リクエストマッピングドキュメントに条件式を指定することができます。また、条件チェックでエラーが検出され、オブジェクトが更新されなかった場合に従う処理も指定できます。
例 1
以下の PutItem マッピングドキュメントには条件式がありません。その結果、同じキーに対応する項目がすでにある場合でも、項目は DynamoDB に挿入され、それにより既存の項目が上書きされます。
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "1" } } }
例 2
次の PutItem マッピングドキュメントには条件式があります。この場合、同じキーの項目が DynamoDB に存在しない場合のみ処理が成功します。
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "1" } }, "condition" : { "expression" : "attribute_not_exists(id)" } }
デフォルトでは、条件チェックが失敗した場合、AWS AppSync DynamoDB リゾルバーはミューテーションのエラーを返します。ただし、AWS AppSync DynamoDB のリゾルバーにより追加の機能を提供して、一般的なエッジケースを開発者が処理することもできます。
-
AWS AppSync DynamoDB のリゾルバーにより、DynamoDB の現在値が必要な結果と一致すると判断できる場合、処理は成功として扱われます。
-
エラーを返す代わりに、リゾルバーを設定してカスタムの Lambda 関数を呼び出し、AWS AppSync DynamoDB のリゾルバーがエラーを処理する方法を決定することができます。
これらの詳細については、「条件チェックでのエラーを処理する」セクションを参照してください。
DynamoDB の条件式の詳細については、「DynamoDB ConditionExpressions のドキュメント」を参照してください。
条件を指定する
PutItem、UpdateItem、および DeleteItem の各リクエストマッピングドキュメントはすべて、オプションで condition セクションが指定できます。省略した場合、条件チェックは実行されません。指定した場合、処理が成功するには、条件が true となる必要があります。
condition セクションは以下の構造を持ちます。
"condition" : { "expression" : "someExpression" "expressionNames" : { "#foo" : "foo" }, "expressionValues" : { ":bar" : ... typed value }, "equalsIgnore" : [ "version" ], "consistentRead" : true, "conditionalCheckFailedHandler" : { "strategy" : "Custom", "lambdaArn" : "arn:..." } }
以下のフィールドに条件を指定します。
-
expression -
更新式そのものを指定します。条件式の記述方法の詳細については、DynamoDB ConditionExpressions のドキュメントを参照してください。このフィールドの指定は必須です。
-
expressionNames -
式の属性名のプレースホルダーを示します。キー - 値のペアの形式になります。キーは expression で使用される名前のプレースホルダーに対応し、値は DynamoDB の項目の属性名と一致する文字列でなければなりません。このフィールドはオプションであり、expression で使用される式の属性名のプレースホルダーのみを入力します。
-
expressionValues -
式の属性値のプレースホルダーを示します。キー - 値のペアの形式になります。キーは expression で使用される値のプレースホルダーに対応し、値は型付き値でなければなりません。「型付き値」を指定する方法の詳細については、「型システム (リクエストマッピング)」を参照してください。この指定は必須です。このフィールドはオプションであり、expression で使用される式の属性値のプレースホルダーのみを入力します。
残りのフィールドは、AWS AppSync DynamoDB のリゾルバーに条件チェックで検出したエラーを処理する方法を指示します。
-
equalsIgnore -
PutItem処理の使用時に条件チェックでエラーが検出された場合、AWS AppSync DynamoDB のリゾルバーは DynamoDB に現在ある項目と、書き込もうとした項目とを比較します。これらが同じ場合、処理は成功として扱われます。equalsIgnoreフィールドを使用して、AWS AppSync がこの比較を実行する際に無視する属性のリストを指定することができます。たとえば、唯一の違いがversion属性である場合、オペレーションは成功として扱われます。このフィールドはオプションです。 -
consistentRead -
条件チェックでエラーが検出された場合、AWS AppSync は強力な整合性のある読み込みを使用して DynamoDB から項目の現在の値を取得します。このフィールドを使用して、結果整合性のある読み込みを代わりに使用するよう AWS AppSync DynamoDB のリゾルバーに指示することができます。このフィールドはオプションであり、デフォルトは
trueです。 -
conditionalCheckFailedHandler -
このセクションでは、AWS AppSync DynamoDB のリゾルバーが DynamoDB の現在値と期待値を比較した後、条件チェックでエラーが検出された場合に、これを処理する方法を指定することができます。このセクションはオプションです。省略した場合、デフォルトの処理は
Rejectです。-
strategy -
AWS AppSync DynamoDB のリゾルバーが DynamoDB の現在値と期待値を比較した後に行う処理です。このフィールドは必須であり、以下を値を設定できます。
-
Reject -
ミューテーションは失敗し、GraphQL レスポンスにエラーが追加されます。
-
Custom -
AWS AppSync DynamoDB のリゾルバーはカスタムの Lambda 関数を呼び出して、条件チェックで検出したエラーの処理方法を決定します。
strategyがCustomに設定されている場合、lambdaArnフィールドには、呼び出す Lambda 関数の ARN が含まれている必要があります。
-
-
lambdaArn -
AWS AppSync DynamoDB のリゾルバーが、条件チェックで検出されたエラーを処理する方法を決定するために呼び出す Lambda 関数の ARN です。このフィールドは、
strategyがCustomに設定されている場合のみ指定する必要があります。この機能の使用方法の詳細については、「条件チェックでのエラーを処理する」を参照してください。
-
条件チェックでのエラーを処理する
デフォルトでは、条件チェックでエラーが検出されると、AWS AppSync DynamoDB リゾルバーは、ミューテーションに関するエラーを返すとともに、DynamoDB のオブジェクトの現在値を返します。ただし、AWS AppSync DynamoDB のリゾルバーにより追加の機能を提供して、一般的なエッジケースを開発者が処理することもできます。
-
AWS AppSync DynamoDB のリゾルバーにより、DynamoDB の現在値が必要な結果と一致すると判断できる場合、処理は成功として扱われます。
-
エラーを返す代わりに、リゾルバーを設定してカスタムの Lambda 関数を呼び出し、AWS AppSync DynamoDB のリゾルバーがエラーを処理する方法を決定することができます。
このプロセスのフローチャートは次のとおりです。
必要な結果をチェックする
条件チェックでエラーが検出された場合、AWS の AppSync DynamoDB リゾルバーは GetItem DynamoDB リクエストを実行し、DynamoDB から項目の現在値を取得します。デフォルトでは、強力な整合性のある読み込みを使用しますが、consistentRead ブロックの condition フィールドを使用してこれを設定し、この値を期待した結果と比較することができます。
-
PutItem処理では、AWS の AppSync DynamoDB リゾルバーは、equalsIgnoreにリストされた以外の属性について、現在値と書き込もうとした値を比較します。項目が同じ場合は、処理は成功として扱われ、DynamoDB から取得された項目が返されます。それ以外の場合は、設定された処理に従います。たとえば、
PutItemリクエストマッピングドキュメントが以下のようになっているとします。{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "1" } }, "attributeValues" : { "name" : { "S" : "Steve" }, "version" : { "N" : 2 } }, "condition" : { "expression" : "version = :expectedVersion", "expressionValues" : { ":expectedVersion" : { "N" : 1 } }, "equalsIgnore": [ "version" ] } }現在、DynamoDB にある項目は以下のようになりました。
{ "id" : { "S" : "1" }, "name" : { "S" : "Steve" }, "version" : { "N" : 8 } }この場合、AWS の AppSync DynamoDB リゾルバーは書き込もうとした項目を現在の値と比較し、
versionフィールドのみ異なっていることを検出します。ただし、versionフィールドは無視するよう設定されているため、処理は成功として扱われ、DynamoDB から取得された項目が返されます。 -
DeleteItem処理では、 AWS の AppSync DynamoDB リゾルバーは項目が DynamoDB から返されたことを確認します。項目が返されなかった場合、処理は成功として扱われます。それ以外の場合は、設定された処理に従います。 -
UpdateItem処理では、 AWS の AppSync DynamoDBリゾルバーには、DynamoDB に現在ある項目が期待した結果と一致するかどうかを判定するための十分な情報がないため、設定された処理に従います。
DynamoDB のオブジェクトの現在の状態が期待した結果と異なる場合、AWS の AppSync DynamoDB リゾルバーは設定された処理に従い、ミューテーションを拒否するか、Lambda 関数を呼び出して次の処理を決定します。
「reject」の戦略に従う
Reject 戦略に従うと、AWS AppSync DynamoDB リゾルバーはミューテーションのエラーを返します。
たとえば、次のミューテーションリクエストが指定されたとします。
mutation { updatePerson(id: 1, name: "Steve", expectedVersion: 1) { Name theVersion } }
DynamoDB から返された項目が以下のようになっているとします。
{ "id" : { "S" : "1" }, "name" : { "S" : "Steve" }, "version" : { "N" : 8 } }
また、レスポンスマッピングテンプレートは以下のようになっているとします。
{ "id" : $util.toJson($context.result.id), "Name" : $util.toJson($context.result.name), "theVersion" : $util.toJson($context.result.version) }
GraphQL レスポンスは以下のようになります。
{ "data": null, "errors": [ { "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" "errorType": "DynamoDB:ConditionalCheckFailedException", ... } ] }
また、返されたオブジェクトのフィールドすべてが他のリゾルバーによって入力され、そのミューテーションが成功した場合、オブジェクトが error セクションに返されたときに、それらのフィールドは解決されません。
「custom」戦略に従う
Custom 戦略に従う場合、AWS の AppSync DynamoDB リゾルバーは Lambda 関数を呼び出して、以下の処理を決定します。Lambda 関数は以下のオプションのいずれかを選択します。
-
ミューテーション を
rejectする これを指定すると、AWS の AppSync DynamoDB リゾルバーは設定された戦略がRejectされたものとして処理し、前のセクションで説明したように、ミューテーションに関するエラーと DynamoDB のオブジェクトの現在値を返します。 -
ミューテーション を
discardする これを指定すると、AWS の AppSync DynamoDB リゾルバーは条件チェックで検出されたエラーを通知することなく無視し、DynamoDB の値を返します。 -
ミューテーション を
retryする これを指定すると、AWS の AppSync DynamoDB リゾルバーは新しいリクエストマッピングドキュメントを使用してミューテーションを再試行します。
Lambda 呼び出しリクエスト
AWS の AppSync DynamoDB リゾルバーは、lambdaArn で指定された Lambda 関数を呼び出します。また、データソースに設定されたものと同じ service-role-arn を使用します。呼び出しのペイロードは以下の構造を持ちます。
{ "arguments": { ... }, "requestMapping": {... }, "currentValue": { ... }, "resolver": { ... }, "identity": { ... } }
各フィールドの定義は以下のようになります。
-
arguments -
GraphQL ミューテーションの引数です。これは、
$context.argumentsのリクエストマッピングドキュメントで使用できる引数と同じです。 -
requestMapping -
この処理のリクエストマッピングドキュメントです。
-
currentValue -
DynamoDB のオブジェクトの現在値。
-
resolver -
AWS AppSync リゾルバーに関する情報。
-
identity -
呼び出し元に関する情報。これは、
$context.identityのリクエストマッピングドキュメントで使用できる識別情報と同じです。
完全なペイロードの例を次に示します。
{ "arguments": { "id": "1", "name": "Steve", "expectedVersion": 1 }, "requestMapping": { "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "1" } }, "attributeValues" : { "name" : { "S" : "Steve" }, "version" : { "N" : 2 } }, "condition" : { "expression" : "version = :expectedVersion", "expressionValues" : { ":expectedVersion" : { "N" : 1 } }, "equalsIgnore": [ "version" ] } }, "currentValue": { "id" : { "S" : "1" }, "name" : { "S" : "Steve" }, "version" : { "N" : 8 } }, "resolver": { "tableName": "People", "awsRegion": "us-west-2", "parentType": "Mutation", "field": "updatePerson", "outputType": "Person" }, "identity": { "accountId": "123456789012", "sourceIp": "x.x.x.x", "user": "AIDAAAAAAAAAAAAAAAAAA", "userArn": "arn:aws:iam::123456789012:user/appsync" } }
Lambda 呼び出しレスポンス
Lambda 関数は、呼び出しペイロードを確認し、任意のビジネスロジックを適用して、AWS の AppSync DynamoDB リゾルバーがエラーを処理する方法を決定することができます。条件チェックで検出されたエラーを処理するために、以下の 3 つのオプションが指定できます。
-
ミューテーション を
rejectする このオプションのレスポンスペイロードは次の構造を持ちます。{ "action": "reject" }これを指定すると、AWS の AppSync DynamoDB リゾルバーは設定された戦略が
Rejectされたものとして処理し、上記のセクションで説明したように、ミューテーションに関するエラーと DynamoDB のオブジェクトの現在値を返します。 -
ミューテーション を
discardする このオプションのレスポンスペイロードは次の構造を持ちます。{ "action": "discard" }これを指定すると、AWS の AppSync DynamoDB リゾルバーは条件チェックで検出されたエラーを通知することなく無視し、DynamoDB の値を返します。
-
ミューテーション を
retryする このオプションのレスポンスペイロードは次の構造を持ちます。{ "action": "retry", "retryMapping": { ... } }これを指定すると、AWS の AppSync DynamoDB リゾルバーは新しいリクエストマッピングドキュメントを使用してミューテーションを再試行します。
retryMappingセクションの構造は DynamoDB の処理によって異なり、その処理の完全なリクエストマッピングドキュメントのサブセットとなります。PutItemの場合、retryMappingセクションは次の構造を持ちます。attributeValuesフィールドについては、「PutItem」を参照してください。{ "attributeValues": { ... }, "condition": { "equalsIgnore" = [ ... ], "consistentRead" = true } }UpdateItemの場合、retryMappingセクションは次の構造を持ちます。updateセクションについては、「UpdateItem」を参照してください。{ "update" : { "expression" : "someExpression" "expressionNames" : { "#foo" : "foo" }, "expressionValues" : { ":bar" : ... typed value } }, "condition": { "consistentRead" = true } }DeleteItemの場合、retryMappingセクションは次の構造を持ちます。{ "condition": { "consistentRead" = true } }使用する別の処理やキーを指定する方法はありません。AWS AppSync DynamoDB のリゾルバーは、同じオブジェクトに対する同じ処理の再試行のみが可能です。また、
conditionセクションではconditionalCheckFailedHandlerは指定できません。再試行が失敗した場合、AWS の AppSync DynamoDB リゾルバーはRejectの戦略に従います。
以下は、失敗した PutItem リクエストを処理する Lambda 関数の例です。ビジネスロジックは呼び出し元を調べます。呼び出し元が jeffTheAdmin の場合は、リクエストを再試行して、現在 DynamoDB にある項目の version と expectedVersion を更新します。それ以外の場合は、ミューテーションを拒否します。
exports.handler = (event, context, callback) => { console.log("Event: "+ JSON.stringify(event)); // Business logic goes here. var response; if ( event.identity.user == "jeffTheAdmin" ) { response = { "action" : "retry", "retryMapping" : { "attributeValues" : event.requestMapping.attributeValues, "condition" : { "expression" : event.requestMapping.condition.expression, "expressionValues" : event.requestMapping.condition.expressionValues } } } response.retryMapping.attributeValues.version = { "N" : event.currentValue.version.N + 1 } response.retryMapping.condition.expressionValues[':expectedVersion'] = event.currentValue.version } else { response = { "action" : "reject" } } console.log("Response: "+ JSON.stringify(response)) callback(null, response) };