AppSync×DynamoDB（UPDATE編）

# 概要
  AppSyncとDynamoDBを使用した簡易的なAPIの作成方法を紹介します。
  
  この記事では、DBのデータを変更する処理を紹介します。

# 前提条件
  - DynamoDBが用意されていること

# AppSync

## スキーマ
  ```graphql
  input CreateRadioInput {
    id: ID!
    program_name: String
    cast: [String!]
    weekday: Int
    time: String
    favorite: Boolean
  }

  type Mutation {
    createRadio(input: CreateRadioInput!): Radio
    updateRadio(input: UpdateRadioInput!): Radio # 今回追加する箇所
  }

  type Query {
    getRadio(id: ID!): Radio
    listRadio(filter: TableRadioFilterInput, limit: Int, nextToken: String): RadioConnection
  }

  type Radio {
    id: ID!
    program_name: String
    cast: [String!]
    weekday: Int
    time: String
    favorite: Boolean
  }

  type RadioConnection {
    items: [Radio]
    nextToken: String
  }

  input TableBooleanFilterInput {
    ne: Boolean
    eq: Boolean
  }

  input TableIntFilterInput {
    ne: Int
    eq: Int
    le: Int
    lt: Int
    ge: Int
    gt: Int
    contains: Int
    notContains: Int
    between: [Int]
  }

  input TableRadioFilterInput {
    day: TableIntFilterInput
    time: TableStringFilterInput
    favorite: TableBooleanFilterInput
  }

  input TableStringFilterInput {
    ne: String
    eq: String
    le: String
    lt: String
    ge: String
    gt: String
    contains: String
    notContains: String
    between: [String]
    beginsWith: String
  }

  # 今回追加する箇所
  input UpdateRadioInput {
    id: ID!
    program_name: String
    cast: [String!]
    day: Int
    time: String
    favorite: Boolean
  }
  ```

## リゾルバー
  - リゾルバーのQueryから``updateRadio(...): Radio``の``アタッチ``を選択

### リクエストマッピングテンプレート
  ```vtl
  {
    "version": "2017-02-28",
    "operation": "UpdateItem",
    "key": {
      "id": $util.dynamodb.toDynamoDBJson($ctx.args.input.id),
    },

    ## Set up some space to keep track of things we're updating **
    #set( $expNames  = {} )
    #set( $expValues = {} )
    #set( $expSet = {} )
    #set( $expAdd = {} )
    #set( $expRemove = [] )

    ## Iterate through each argument, skipping keys **
    #foreach( $entry in $util.map.copyAndRemoveAllKeys($ctx.args.input, ["id"]).entrySet() )
      #if( $util.isNull($entry.value) )
        ## If the argument is set to "null", then remove that attribute from the item in DynamoDB **

        #set( $discard = ${expRemove.add("#${entry.key}")} )
        $!{expNames.put("#${entry.key}", "${entry.key}")}
      #else
        ## Otherwise set (or update) the attribute on the item in DynamoDB **

        $!{expSet.put("#${entry.key}", ":${entry.key}")}
        $!{expNames.put("#${entry.key}", "${entry.key}")}
        $!{expValues.put(":${entry.key}", $util.dynamodb.toDynamoDB($entry.value))}
      #end
    #end

    ## Start building the update expression, starting with attributes we're going to SET **
    #set( $expression = "" )
    #if( !${expSet.isEmpty()} )
      #set( $expression = "SET" )
      #foreach( $entry in $expSet.entrySet() )
        #set( $expression = "${expression} ${entry.key} = ${entry.value}" )
        #if ( $foreach.hasNext )
          #set( $expression = "${expression}," )
        #end
      #end
    #end

    ## Continue building the update expression, adding attributes we're going to ADD **
    #if( !${expAdd.isEmpty()} )
      #set( $expression = "${expression} ADD" )
      #foreach( $entry in $expAdd.entrySet() )
        #set( $expression = "${expression} ${entry.key} ${entry.value}" )
        #if ( $foreach.hasNext )
          #set( $expression = "${expression}," )
        #end
      #end
    #end

    ## Continue building the update expression, adding attributes we're going to REMOVE **
    #if( !${expRemove.isEmpty()} )
      #set( $expression = "${expression} REMOVE" )

      #foreach( $entry in $expRemove )
        #set( $expression = "${expression} ${entry}" )
        #if ( $foreach.hasNext )
          #set( $expression = "${expression}," )
        #end
      #end
    #end

    ## Finally, write the update expression into the document, along with any expressionNames and expressionValues **
    "update": {
      "expression": "${expression}",
      #if( !${expNames.isEmpty()} )
        "expressionNames": $utils.toJson($expNames),
      #end
      #if( !${expValues.isEmpty()} )
        "expressionValues": $utils.toJson($expValues),
      #end
    },

    "condition": {
      "expression": "attribute_exists(#id)",
      "expressionNames": {
        "#id": "id",
      },
    }
  }
  ```

### レスポンスマッピングテンプレート
  ```vtl
  $util.toJson($ctx.result)
  ```

# 実行
  - クエリを実行する
    - 画面左が実行クエリ、画面右が実行結果
    ![クエリ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/4b3a9ead-c79e-dab4-01e8-881db2ac8e57.png)
  - DynamoDBのデータが変更されていることの確認
  ![DynamoDB](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2318120/0b4db934-9953-2976-c49b-b24d773db1b3.png)