• 沒有找到結果。

Modifying the updatePost Resolver (DynamoDB UpdateItem)

在文檔中 AWS AppSync (頁 68-72)

• Choose Execute query (the orange play button).

• The updated post in DynamoDB should appear in the results pane to the right of the query pane. It should look similar to the following:

{ "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 }

} }

In this example, the ups and downs fields were not modified because the request mapping template did not ask AWS AppSync and DynamoDB to do anything with those fields. Also, the version field was incremented by 1 because you asked AWS AppSync and DynamoDB to add 1 to the version field.

Modifying the updatePost Resolver (DynamoDB UpdateItem)

This is a good start to the updatePost mutation, but it has two main problems:

• If you want to update just a single field, you have to update all of the fields.

• If two people are modifying the object, you could potentially lose information.

To address these issues, you’re going to modify the updatePost mutation to only modify arguments that were specified in the request, and then add a condition to the UpdateItem operation.

• Choose the Schema tab.

• In the Schema pane, modify the updatePost field in the Mutation type to remove the exclamation marks from the author, title, content, and url arguments, making sure to leave the id field as is.

This will make them optional argument. Also, add a new, required expectedVersion argument.

type Mutation { updatePost(

id: ID!, author: String, title: String, content: String, url: String,

expectedVersion: Int!

): Post addPost(

author: String!

title: String!

Modifying the updatePost

• In the Data types pane on the right, find the updatePost field on the Mutation type.

• Choose PostDynamoDBTable to open the existing resolver.

• In Configure the request mapping template, modify the request mapping template as follows:

{

"version" : "2017-02-28", "operation" : "UpdateItem", "key" : {

"id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) },

$!{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" )

## Start building the update expression, starting with attributes you're going to SET **

## Continue building the update expression, adding attributes you're going to ADD **

#if( !${expAdd.isEmpty()} )

#set( $expression = "${expression} ADD" ) #foreach( $entry in $expAdd.entrySet() )

Modifying the updatePost Resolver (DynamoDB UpdateItem)

#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) }

} }

• Choose Save.

This template is one of the more complex examples. It demonstrates the power and flexibility of mapping templates. It loops through all of the arguments, skipping over id and expectedVersion.

If the argument is set to something, it asks AWS AppSync and DynamoDB to update that attribute on the object in DynamoDB. If the attribute is set to null, it asks AWS AppSync and DynamoDB to remove that attribute from the post object. If an argument wasn’t specified, it leaves the attribute alone. It also increments the version field.

Also, there is a new condition section. A condition expression enables you tell AWS AppSync and DynamoDB whether or not the request should succeed based on the state of the object already in DynamoDB before the operation is performed. In this case, you only want the UpdateItem request to succeed if the version field of the item currently in DynamoDB exactly matches the expectedVersion argument.

For more information about condition expressions, see the Condition Expressions (p. 335) reference documentation.

Call the API to Update a Post

Let’s try updating the Post object with the new resolver:

Modifying the updatePost Resolver (DynamoDB UpdateItem)

• Choose the Queries tab.

• In the Queries pane, paste the following mutation. You’ll also need to update the id argument to the value you noted down earlier.

mutation updatePost { updatePost(

id:123

title: "An empty story"

content: null expectedVersion: 2 ) {

id author title content url ups downs version }}

• Choose Execute query (the orange play button).

• The updated post in DynamoDB should appear in the results pane to the right of the query pane. It should look similar to the following:

{ "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). You set the title attribute to a new value, and removed the content attribute from the post. The author, url, ups, and downs fields were left untouched.

Try executing the mutation request again, leaving the request exactly as is. You should see a response similar to the following:

{

"data": {

"updatePost": null },

"errors": [ {

"path": [ "updatePost"

], "data": { "id": "123",

Create upvotePost and downvotePost Mutations (DynamoDB UpdateItem) "author": "A new author",

"title": "An empty story", "content": null,

"url": "https://aws.amazon.com/appsync/", "ups": 1,

"downs": 0, "version": 3 },

"errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [

{

"line": 2, "column": 3 }

],

"message": "The conditional request failed (Service: AmazonDynamoDBv2;

Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID:

ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)"

} ]}

The request fails because the condition expression evaluates to false:

• The first time you ran the request, the value of the version field of the post in DynamoDB was 2, which matched the expectedVersion argument. The request succeeded, which meant the version field was incremented in DynamoDB to 3.

• The second time you ran the request, the value of the version field of the post in DynamoDB was 3, which did not match the expectedVersion argument.

This pattern is typically called optimistic locking.

A feature of an AWS AppSync DynamoDB resolver is that it returns the current value of the post object in DynamoDB. You can find this in the data field in the errors section of the GraphQL response.

Your application can use this information to decide how it should proceed. In this case, you can see the version field of the object in DynamoDB is set to 3, so you could just update the expectedVersion argument to 3 and the request would succeed again.

For more information about handling condition check failures, see the Condition Expressions (p. 335) mapping template reference documentation.

Create upvotePost and downvotePost Mutations

在文檔中 AWS AppSync (頁 68-72)

相關文件