

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 条件式
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-expressions"></a>

`PutItem`、`UpdateItem`、および `DeleteItem` の各 DynamoDB 処理を使用して DynamoDB のオブジェクトをミューテーションする場合、オプションで、処理を実行する前に、DynamoDB にある既存のオブジェクトの状態に基づいてリクエストが成功するかどうかを制御する条件式を指定することができます。

 AWS AppSync DynamoDB 関数を使用すると、`PutItem`、、`UpdateItem`および `DeleteItem`リクエストオブジェクトで条件式を指定できます。また、条件が失敗し、オブジェクトが更新されなかった場合に従う戦略も指定できます。

## 例 1
<a name="js-id19"></a>

以下の `PutItem` リクエストオブジェクトには条件式がありません。その結果、同じキーに対応する項目がすでにある場合でも、項目は DynamoDB に挿入され、それにより既存の項目が上書きされます。

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, ...values} = ctx.args
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({foo, bar}),
    attributeValues: util.dynamodb.toMapValues(values),
  };
}
```

## 例 2
<a name="js-id20"></a>

次の `PutItem` オブジェクトには条件式があります。この場合、同じキーの項目が DynamoDB に存在*しない*場合のみ処理が成功します。

```
import { util } from '@aws-appsync/utils';
export function request(ctx) {
  const { foo, bar, ...values} = ctx.args
  return {
    operation: 'PutItem',
    key: util.dynamodb.toMapValues({foo, bar}),
    attributeValues: util.dynamodb.toMapValues(values),
    condition: { expression: "attribute_not_exists(id)" }
  };
}
```

デフォルトでは、条件チェックが失敗した場合、 AWS AppSync DynamoDB 関数はミューテーションにエラーを提供します。

ただし、 AWS AppSync DynamoDB 関数には、開発者が一般的なエッジケースを処理するのに役立ついくつかの追加機能があります。
+  AWS AppSync DynamoDB 関数は、DynamoDB の現在の値が目的の結果と一致すると判断できる場合、オペレーションを成功したかのように扱います。
+ エラーを返す代わりに、カスタム Lambda 関数を呼び出して、 AWS AppSync DynamoDB 関数が失敗を処理する方法を決定するように関数を設定できます。

これらの詳細については、「[条件チェックでのエラーを処理する](#condition-check)」セクションを参照してください。

DynamoDB の条件式の詳細については、「[DynamoDB ConditionExpressions のドキュメント](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html)」を参照してください。

## 条件を指定する
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-specification"></a>

`PutItem`、`UpdateItem`、および `DeleteItem` の各リクエストオブジェクトはすべて、オプションで `condition` セクションが指定できます。省略した場合、条件チェックは実行されません。指定した場合、処理が成功するには、条件が true となる必要があります。

`condition` セクションは以下の構造を持ちます。

```
type ConditionCheckExpression = {
  expression: string;
  expressionNames?: { [key: string]: string};
  expressionValues?: { [key: string]: any};
  equalsIgnore?: string[];
  consistentRead?: boolean;
  conditionalCheckFailedHandler?: {
    strategy: 'Custom' | 'Reject';
    lambdaArn?: string;
  };
};
```

以下のフィールドに条件を指定します。

** `expression` **  
更新式そのものを指定します。条件式の記述方法の詳細については、[DynamoDB ConditionExpressions のドキュメント](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.ConditionExpressions.html)を参照してください。このフィールドの指定は必須です。

** `expressionNames` **  
式の属性名のプレースホルダーを示します。キー - 値のペアの形式になります。キーは *expression* で使用される名前のプレースホルダーに対応し、値は DynamoDB の項目の属性名と一致する文字列でなければなりません。このフィールドはオプションであり、*expression* で使用される式の属性名のプレースホルダーのみを入力します。

** `expressionValues` **  
式の属性値のプレースホルダーを示します。キー - 値のペアの形式になります。キーは expression で使用される値のプレースホルダーに対応し、値は型付き値でなければなりません。「型付き値」を指定する方法の詳細については、「[型システム (リクエストマッピング)](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-typed-values-request)」を参照してください。この指定は必須です。このフィールドはオプションであり、expression で使用される式の属性値のプレースホルダーのみを入力します。

残りのフィールドは、 AWS AppSync DynamoDB 関数に条件チェックの失敗を処理する方法を指示します。

** `equalsIgnore` **  
`PutItem` オペレーションの使用時に条件チェックが失敗すると、 AWS AppSync DynamoDB 関数は、DynamoDB の現在の項目と、書き込みを試みた項目を比較します。これらが同じ場合、処理は成功として扱われます。`equalsIgnore` フィールドを使用して、 AWS AppSync がその比較を実行するときに無視する属性のリストを指定できます。たとえば、唯一の違いが `version` 属性である場合、オペレーションは成功として扱われます。このフィールドはオプションです。

** `consistentRead` **  
条件チェックが失敗すると、 AWS AppSync は強力な整合性のある読み込みを使用して DynamoDB から項目の現在の値を取得します。このフィールドを使用して、結果整合性のある読み込みを代わりに使用するよう AWS AppSync DynamoDB の関数に指示することができます。このフィールドはオプションであり、デフォルトは `true` です。

** `conditionalCheckFailedHandler` **  
このセクションでは、DynamoDB の現在の値と予想される結果を比較した後、 AWS AppSync 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` に設定されている場合のみ指定する必要があります。この機能の使用方法の詳細については、「[条件チェックでのエラーを処理する](#condition-check)」を参照してください。

## 条件チェックでのエラーを処理する
<a name="js-aws-appsync-resolver-reference-dynamodb-condition-handling"></a>

条件チェックが失敗すると、 AWS AppSync DynamoDB 関数は `util.appendError`ユーティリティを使用して、ミューテーションのエラーとオブジェクトの現在の値を渡すことができます。ただし、 AWS AppSync DynamoDB 関数には、開発者が一般的なエッジケースを処理するのに役立ついくつかの追加機能があります。
+  AWS AppSync DynamoDB 関数は、DynamoDB の現在の値が目的の結果と一致すると判断できる場合、オペレーションを成功したかのように扱います。
+ エラーを返す代わりに、カスタム Lambda 関数を呼び出して、 AWS AppSync DynamoDB 関数が失敗を処理する方法を決定するように関数を設定できます。

このプロセスのフローチャートは次のとおりです。

![\[Flowchart showing process for transforming requests with mutation attempts and value checks.\]](http://docs.aws.amazon.com/ja_jp/appsync/latest/devguide/images/DynamoDB-condition-check-failure-handling.png)


### 必要な結果をチェックする
<a name="js-checking-for-the-desired-result"></a>

条件チェックが失敗すると、 AWS AppSync DynamoDB 関数は `GetItem` DynamoDB リクエストを実行して、DynamoDB から項目の現在の値を取得します。デフォルトでは、強力な整合性のある読み込みを使用しますが、`condition` ブロックの `consistentRead` フィールドを使用してこれを設定し、この値を期待した結果と比較することができます。
+ `PutItem` オペレーションの場合、 AWS AppSync DynamoDB 関数は、現在の値を書き込みを試みた値と比較します。ただし、 にリストされている属性は比較`equalsIgnore`から除外されます。項目が同じ場合は、処理は成功として扱われ、DynamoDB から取得された項目が返されます。それ以外の場合は、設定された処理に従います。

  たとえば、`PutItem` リクエストオブジェクトが以下のようになっているとします。

  ```
  import { util } from '@aws-appsync/utils';
  export function request(ctx) {
    const { id, name, version} = ctx.args
    return {
      operation: 'PutItem',
      key: util.dynamodb.toMapValues({foo, bar}),
      attributeValues: util.dynamodb.toMapValues({ name, version: version+1 }),
      condition: { 
        expression: "version = :expectedVersion",
        expressionValues: util.dynamodb.toMapValues({':expectedVersion': version}),
        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」の戦略に従う
<a name="js-following-the-reject-strategy"></a>

`Reject` 戦略に従うと、 AWS AppSync DynamoDB 関数はミューテーションのエラーを返します。

たとえば、次のミューテーションリクエストが指定されたとします。

```
mutation {
    updatePerson(id: 1, name: "Steve", expectedVersion: 1) {
        Name
        theVersion
    }
}
```

DynamoDB から返された項目が以下のようになっているとします。

```
{
   "id" : { "S" : "1" },
   "name" : { "S" : "Steve" },
   "version" : { "N" : 8 }
}
```

この関数レスポンスハンドラーは次のようになります。

```
import { util } from '@aws-appsync/utils';
export function response(ctx) {
  const { version, ...values } = ctx.result;
  const result = { ...values, theVersion: version };
  if (ctx.error) {
    if (error) {
      return util.appendError(error.message, error.type, result, null);
    }
  }
  return result
}
```

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」戦略に従う
<a name="js-following-the-custom-strategy"></a>

`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 関数は、 で指定された Lambda 関数を呼び出します`lambdaArn`。また、データソースに設定されたものと同じ `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](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-putitem)」を参照してください。

  ```
  {
      "attributeValues": { ... },
      "condition": {
          "equalsIgnore" = [ ... ],
          "consistentRead" = true
      }
  }
  ```

  `UpdateItem` の場合、`retryMapping` セクションは次の構造を持ちます。`update` セクションについては、「[UpdateItem](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference-dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-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)
};
```