We’ll set up a new mutation to allow us to update object. We’ll do this using the UpdateItem DynamoDB operation.
updatePost(
id: ID!,
author: String!,
title: String!,
content: String!,
url: String!
): Post
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
"update" : {
"expression" : "SET author = :author, title = :title, content = :content, #url = :url ADD version :one",
"expressionNames": {
"#url" : "url"
},
"expressionValues": {
":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author),
":title" : $util.dynamodb.toDynamoDBJson($context.arguments.title),
":content" : $util.dynamodb.toDynamoDBJson($context.arguments.content),
":url" : $util.dynamodb.toDynamoDBJson($context.arguments.url),
":one" : { "N": 1 }
}
}
}
This resolver is using the DynamoDB UpdateItem, which is significantly different from the PutItem operation. Instead of writing the entire item, you’re just asking DynamoDB to update certain attributes. This is done using DynamoDB Update Expressions. You can see the “expression” section under “update”. It says to set the author, title, content and url attributes, and then increment the version field. The expression has placeholders that have names starting with a colon, which are then defined in the expressionValues field. Finally, DynamoDB has reserved words that cannot appear in the expression. For example, url is a reserved word, so to update the url field you can use name placeholders and define them in the expressionNames field.
$utils.toJson($context.result)
mutation updatePost {
updatePost(
id:"123"
author: "A new author"
title: "An updated author!"
content: "Now with updated content!"
url: "https://aws.amazon.com/appsync/"
) {
id
author
title
content
url
ups
downs
version
}
}
{
"data": {
"updatePost": {
"id": "123",
"author": "A new author",
"title": "An updated author!",
"content": "Now with updated content!",
"url": "https://aws.amazon.com/appsync/",
"ups": 1,
"downs": 0,
"version": 2
}
}
}
Once the updating did, the version attribute is incremented by one unit because we asked AWS AppSync and DynamoDB to add a unit to the version attribute each time we update.
When you use the updatePost mutation as above, there will be 2 problems:
updatePost(
id: ID!,
author: String,
title: String,
content: String,
url: String,
expectedVersion: Int!
): Post
In the Resolvers pane on the right, find the addPost field on the Mutation tyoe, and then choose Attach
Paste the following content to Configure the request mapping template
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
## Set up some space to keep track of things you're updating **
#set( $expNames = {} )
#set( $expValues = {} )
#set( $expSet = {} )
#set( $expAdd = {} )
#set( $expRemove = [] )
## Increment "version" by 1 **
$!{expAdd.put("version", ":one")}
$!{expValues.put(":one", { "N" : 1 })}
## Iterate through each argument, skipping "id" and "expectedVersion" **
#foreach( $entry in $context.arguments.entrySet() )
#if( $entry.key != "id" && $entry.key != "expectedVersion" )
#if( (!$entry.value) && ("$!{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}", { "S" : "${entry.value}" })}
#end
#end
#end
## Start building the update expression, starting with attributes you'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 you'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 you'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" : "version = :expectedVersion",
"expressionValues" : {
":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion)
}
}
}
mutation updatePost {
updatePost(
id:123
title: "An empty story"
content: null
expectedVersion: 2
) {
id
author
title
content
url
ups
downs
version
}
}
{
"data": {
"updatePost": {
"id": "123",
"author": "A new author",
"title": "An empty story",
"content": null,
"url": "https://aws.amazon.com/appsync/",
"ups": 1,
"downs": 0,
"version": 3
}
}
}
In this request, you asked AWS AppSync and DynamoDB to update the title and content field only. It left all the other fields alone (other than incrementing the version field)
The request fails because the condition expression evaluates to false:
Chúng ta sẽ tạo hai mutation mới để cập nhật trường ups và downs để ghi lại lượt ủng hộ hay phản đối cho bài đăng
upvotePost(id: ID!): Post
downvotePost(id: ID!): Post
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
"update" : {
"expression" : "ADD ups :plusOne, version :plusOne",
"expressionValues" : {
":plusOne" : { "N" : 1 }
}
}
}
$utils.toJson($context.result)
{
"version" : "2017-02-28",
"operation" : "UpdateItem",
"key" : {
"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id)
},
"update" : {
"expression" : "ADD downs :plusOne, version :plusOne",
"expressionValues" : {
":plusOne" : { "N" : 1 }
}
}
}
$utils.toJson($context.result)
mutation votePost {
upvotePost(id:123) {
id
author
title
content
url
ups
downs
version
}
}
{
"data": {
"upvotePost": {
"id": "123",
"author": "A new author",
"title": "An empty story",
"content": null,
"url": "https://aws.amazon.com/appsync/",
"ups": 2,
"downs": 0,
"version": 4
}
}
}
mutation votePost {
downvotePost(id:123) {
id
author
title
content
url
ups
downs
version
}
}