本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
教程:DynamoDB 解析器
本教程展示了如何在中使用您自己的 Amazon DynamoDB 表。AmazonAppSync 并将它们连接到 GraphQL API。
你可以让AmazonAppSync 代表您预配置 DynamoDB 资源。如果您愿意,也可以创建数据源和解析程序,将现有的表连接到 GraphQL 架构。在这两种情况下,您都可以通过 GraphQL 语句读写您的 DynamoDB 数据库,并订阅实时数据。
要将 GraphQL 语句转换为 DynamoDB 操作,并将响应转换回 GraphQL,需要完成一些特定的配置步骤。本教程通过一些现实世界的场景和数据访问模式介绍了配置过程。
设置 DynamoDB 表
要开始此教程,您需要预配置Amazon使用以下内容的资源Amazon CloudFormation模板:
aws cloudformation create-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB \ --template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/dynamodb/AmazonDynamoDBCFTemplate.yaml \ --capabilities CAPABILITY_NAMED_IAM
你可以启动以下Amazon CloudFormation在您的美国西部 2(俄勒冈)区域堆叠Amazonaccount.
这会创建以下内容:
-
名为 DynamoDB 表
AppSyncTutorial-Post
那将保持Post
数据。 -
允许的 IAM 角色和关联的 IAM 托管策略AmazonAppSync 与
Post
TABLE。
要了解堆栈和所创建资源的更多详细信息,请运行以下 CLI 命令:
aws cloudformation describe-stacks \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB
稍后要删除资源,您可以运行以下操作:
aws cloudformation delete-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB
创建您的 GraphQL API
要在中创建 GraphQL APIAmazonAppSync:
-
打开AmazonAppSync 控制台然后选择创建 API.
-
将 API 的名称设置为
AWSAppSyncTutorial
。 -
选择自定义架构。
-
选择创建。
这些区域有:AmazonAppSync 控制台会使用 API 密钥身份验证模式为您创建新的 GraphQL API。您可以根据本教程后面的说明,使用控制台设置 GraphQL API 的其余部分,并针对它运行查询。
定义基本的 Post API
现在你设置了AmazonAppSync GraphQL API,您可以设置基本架构,允许对文章数据进行基本的创建、检索和删除操作。
在AmazonAppSync 控制台,选择架构选项卡。在 Schema (架构) 窗格中,将内容替换为以下代码,然后选择 Save (保存):
schema { query: Query mutation: Mutation } type Query { getPost(id: ID): Post } type Mutation { addPost( id: ID! author: String! title: String! content: String! url: String! ): Post! } type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! }
此架构定义 Post
类型,执行操作以添加并获取 Post
对象。
配置 DynamoDB 表的数据源
接下来,要将架构中定义的查询和更改链接到AppSyncTutorial-Post
DynamoDB 表。
首先,AmazonAppSync 需要知道您的表。要实现此目的,需要在中设置数据源。AmazonAppSync:
-
选择 Data source (数据源) 选项卡。
-
选择 New (新建) 创建新的数据源。
-
对于数据源名称,输入
PostDynamoDBTable
。 -
对于数据源类型,选择 Amazon DynamoDB table (Amazon DynamoDB 表)。
-
对于区域,选择 US-WEST-2。
-
在表的列表中,选择AppSyncTorial-PostDynamoDB 表。
-
在创建或使用现有角色部分,选择现有角色.
-
选择创建。
设置 addPost 解析程序 (DynamoDB PutItem)
晚于AmazonAppSync 知道有 DynamoDB 表,您可以定义,将表与单个查询和更改链接。解析程序. 你创建的第一个解析器是addPost
解析程序,使您能够在AppSyncTutorial-Post
DynamoDB 表。
解析程序具有以下组件:
-
GraphQL 架构中的位置,用于附加解析程序。在本例中,您将设置
addPost
类型的Mutation
字段的解析程序。调用者调用mutation { addPost(...){...} }
时,将调用此解析程序。 -
此解析程序所用的数据源。在本例中,您要使用之前定义的
PostDynamoDBTable
数据源,这样您就可以在AppSyncTutorial-Post
DynamoDB 表中添加条目。 -
请求映射模板。请求映射模板的目的是将调用者的传入请求转换为指令。AmazonAppSync 对 DynamoDB 执行。
-
响应映射模板。响应映射模板的任务是将 DynamoDB 的响应转换回 GraphQL 期待获得的内容。如果 DynamoDB 中的数据形态与 GraphQL 中的
Post
类型不同,此模板很有用。但在此例中它们的形态相同,所以只用于传递数据。
设置解析程序:
-
选择 Schema (架构) 选项卡。
-
在数据类型在右侧的窗格中,找到AddPost字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "attributeValues" : { "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), "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } }
注意:一个类型在所有键和属性值中指定。例如,您将
author
字段设置为{ "S" : "${context.arguments.author}" }
。这些区域有:S
部分指示AmazonAppSync 和 DynamoDB,此值为字符串。实际的值由author
参数填充。与此类似,version
字段是一个数字字段,因为它使用N
作为类型。最后,您还将初始化ups
、downs
和version
字段。在本教程中,您已指定 GraphQL
ID!
类型,它作为客户端参数的一部分,会为插入 DynamoDB 的新项目编制索引。Amazon AppSync附带一个用于自动生成 ID 的实用程序$utils.autoId()
您也可以以的形式使用"id" : { "S" : "${$utils.autoId()}" }
. 然后,就可以在id: ID!
的架构定义中省去addPost()
,因为它将自动插入。在此教程中,您不会使用此方法,但在写入 DynamoDB 表时,可以考虑使用这种方便的方法。有关映射模板的更多信息,请参阅 解析程序映射模板概述参考文档。有关 GetItem 请求映射的更多信息,请参阅 GetItem 参考文档。有关类型的更多信息,请参阅类型系统(请求映射)参考文档。
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
注意:因为中的数据的形状
AppSyncTutorial-Post
表格完全匹配Post
输入 GraphQL,响应映射模板只会直接传递结果。还请注意,此教程中的所有示例均使用同一响应映射模板,所以您只需创建一个文件。 -
选择保存。
调用 API 来添加文章
现在解析程序已设置完成,AmazonAppSync 可以翻译传入addPost
对 DynamoDB PutItem 操作的变异。现在,您可以运行一个更改,在表中添加内容。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改:
mutation addPost { addPost( id: 123 author: "AUTHORNAME" title: "Our first post!" content: "This is our first post." url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
新创建的文章的结果应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "addPost": { "id": "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }
以下是具体过程:
-
AmazonAppSync 收到
addPost
更改请求。 -
AmazonAppSync 利用请求和请求映射模板,生成请求映射文档。如下所示:
{ "version" : "2017-02-28", "operation" : "PutItem", "key" : { "id" : { "S" : "123" } }, "attributeValues" : { "author": { "S" : "AUTHORNAME" }, "title": { "S" : "Our first post!" }, "content": { "S" : "This is our first post." }, "url": { "S" : "https://aws.amazon.com/appsync/" }, "ups" : { "N" : 1 }, "downs" : { "N" : 0 }, "version" : { "N" : 1 } } }
-
AmazonAppSync 使用请求映射文档生成并执行 DynamoDB
PutItem
请求. -
AmazonAppSync 获取了
PutItem
请求并将它们转换回 GraphQL 类型。{ "id" : "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups" : 1, "downs" : 0, "version" : 1 }
-
通过响应映射文档进行传递,没有变化。
-
在 GraphQL 响应中返回新创建的对象。
设置 GetPost 解析程序(DynamoDB GetItem)
现在你可以将数据添加到AppSyncTutorial-Post
DynamoDB 表,您需要设置getPost
查询以便它可以从AppSyncTutorial-Post
TABLE。为了实现此目的,您要设置另一解析程序。
-
选择 Schema (架构) 选项卡。
-
在数据类型在右侧的窗格中,找到getPost字段中的查询键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($ctx.args.id) } }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
调用 API 以获取文章
现在解析器已经设置好了,AmazonAppSync 知道如何翻译来电getPost
查询 DynamoDBGetItem
operation. 现在,您可以运行查询,检索之前创建的文章。
-
选择 Queries 选项卡。
-
在Queries (查询) 窗格中粘贴以下内容:
query getPost { getPost(id:123) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
从 DynamoDB 中检索到的文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "getPost": { "id": "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }
以下是具体过程:
-
AmazonAppSync 收到
getPost
查询请求。 -
AmazonAppSync 利用请求和请求映射模板,生成请求映射文档。如下所示:
{ "version" : "2017-02-28", "operation" : "GetItem", "key" : { "id" : { "S" : "123" } } }
-
AmazonAppSync 使用请求映射文档生成并执行 DynamoDB GetItem 请求。
-
AmazonAppSync 获取了
GetItem
请求并将其转换回 GraphQL 类型。{ "id" : "123", "author": "AUTHORNAME", "title": "Our first post!", "content": "This is our first post.", "url": "https://aws.amazon.com/appsync/", "ups" : 1, "downs" : 0, "version" : 1 }
-
通过响应映射文档进行传递,没有变化。
-
在响应中返回检索到的对象。
创建 updatePost 更改 (DynamoDB UpdateItem)
到目前为止,您可以创建和检索Post
DynamoDB 中的对象。现在,您要设置一项新的更改,以便更新对象。您将使用 UpdateItem DynamoDB 操作实现此目的。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Mutation
类型,添加新的updatePost
更改,如下所示:type Mutation { updatePost( id: ID!, author: String!, title: String!, content: String!, url: String! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的updatePost字段中的更改键入然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "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 } } } }
注意:此解析程序使用的是 DynamoDB UpdateItem,它与 PutItem 操作截然不同。您只要求 DynamoDB 更新某些属性,而不会写入整个项目。这是使用 DynamoDB 更新表达式实现的。表达式本身是在
expression
部分的update
字段中指定的。它会设置author
、title
、content
和 URL 属性,还会递增version
字段。要使用的值不会出现在表达式本身;表达式中的占位符名称以冒号打头,并在expressionValues
字段中进行定义。最后,DynamoDB 还有一些保留关键字是不能出现在中的。expression
. 例如,url
是保留关键字,所以要更新url
字段,您可使用名称占位符,并在expressionNames
字段中定义它们。有关
UpdateItem
请求映射的更多信息,请参阅 UpdateItem 参考文档。有关如何编写更新表达式的更多信息,请参阅 DynamoDB UpdateExpressions 文档。 -
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
调用 API 以更新文章
现在解析器已经设置好了,AmazonAppSync 知道如何翻译来电update
DynamoDB 的突变Update
operation. 现在,您可以运行更改,以更新您之前写入的项目。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。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 } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
在 DynamoDB 中更新的文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "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 } } }
在此示例中,ups
和downs
未修改字段,因为请求映射模板没有要求AmazonAppSync 和 DynamoDB 可以对这些字段执行任何操作。另外,version
因为您要求,字段增加了 1AmazonAppSync 和 DynamoDB 将 1 添加到version
字段中返回的子位置类型。
修改 updatePost 解析程序 (DynamoDB UpdateItem)
updatePost
更改看上去不错,但它有两个主要问题:
-
如果您只希望更新一个字段,则必须更新所有字段。
-
如果两个人同时修改对象,您可能会丢失信息。
为了解决这些问题,您要修改 updatePost
更改,做到只修改请求中指定的参数,然后在 UpdateItem
操作中添加条件。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Mutation
类型中的updatePost
字段,删除author
、title
、content
和url
参数的感叹号,确保id
字段不变。这样它们就会成为可选参数。还要新增一个必需expectedVersion
参数。type Mutation { updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String! title: String! content: String! url: String! ): Post! }
-
选择保存。
-
在数据类型在右侧的窗格中,找到updatePost字段中的更改。
-
选择 PostDynamoDBTable 以打开现有解析程序。
-
在 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) } } }
-
选择保存。
此模板是一个更复杂的示例。它演示了映射模板的强大功能和灵活性。它遍历所有参数,跳过 id
和 expectedVersion
。如果参数设为什么,它会询问。AmazonAppSync 和 DynamoDB 以更新 DynamoDB 中对象的属性。如果属性设置为 null,它会询问。AmazonAppSync 和 DynamoDB,从文章对象中删除该属性。如果未指定参数,该属性会保留原样。它还会递增 version
字段。
还有一个新的 condition
部分。使用条件表达式可以告诉AmazonAppSync 和 DynamoDB 根据执行操作前已在 DynamoDB 中的对象状态,判断请求是否应成功。在这种情况下,您只需要UpdateItem
请求成功如果version
当前位于 DynamoDB 中的项目的字段与expectedVersion
参数。
有关条件表达式的更多信息,请参阅条件表达式参考文档。
调用 API 以更新文章
让我们尝试用新的解析程序更新 Post
对象:
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation updatePost { updatePost( id:123 title: "An empty story" content: null expectedVersion: 2 ) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
在 DynamoDB 中更新的文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "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 } } }
在此请求中,您要求。AmazonAppSync 和 DynamoDB 来更新title
和content
仅限于字段。它不会处理所有其他字段(除了递增 version
字段)。您将 title
属性设为新值,并删除文章的 content
属性。author
、url
、ups
和 downs
字段没有变化。
请尝试再次执行更改请求,保持请求完全不变。您可以看到类似以下内容的响应:
{ "data": { "updatePost": null }, "errors": [ { "path": [ "updatePost" ], "data": { "id": "123", "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)" } ] }
请求失败,因为条件表达式评估为 false:
-
您第一次运行请求时,
version
DynamoDB 中帖子的字段是2
,它匹配expectedVersion
参数。请求成功,意味着version
在 DynamoDB 中将字段增加到3
. -
您第二次运行请求时,
version
DynamoDB 中帖子的字段是3
,这与expectedVersion
参数。
这种模式通常被称为乐观锁。
的一个功能AmazonAppSync DynamoDB 解析程序是,它会返回 DynamoDB 中文章对象的当前值。您可以在 GraphQL 响应的 data
部分的 errors
字段中找到这个值。您的应用程序可以利用此信息决定应如何继续。在这种情况下,您可以看到version
DynamoDB 中对象的字段设置为3
,所以你可以直接更新expectedVersion
参数3
然后请求将再次成功。
有关如何处理条件检查失败的更多信息,请参阅条件表达式映射模板参考文档。
创建 upvotePost 更新和 downvotePost 更改 (DynamoDB UpdateItem)
Post
类型有 ups
和 downs
字段,用于记录赞同投票和反对投票,但现在还无法通过 API 使用它们。让我们添加一些更改,对文章进行赞同和反对投票。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Mutation
类型,添加新的upvotePost
和downvotePost
更改,如下所示:type Mutation { upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的upvotePost字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "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 } } } }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的
downvotePost
字段中的更改键入,然后选择Attach. -
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "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 } } } }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
调用 API,为文章投赞同票或反对票
现在新的解析程序已设置完成,AmazonAppSync 知道如何翻译来电upvotePost
要么downvote
DynamoDB UpdateItem 操作的变异。现在您可以运行更改,为之前创建的文章投赞同票或反对票。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation votePost { upvotePost(id:123) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
在 DynamoDB 中更新的文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "upvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 0, "version": 4 } } }
-
再选择几次 (执行查询) 按钮。您应看到,每次您执行查询时,
ups
和version
字段均会递增 1。 -
更改查询以调用
downvotePost
更改,如下所示:mutation votePost { downvotePost(id:123) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。这次您应看到,每次您执行查询时,
downs
和version
字段均会递增 1。{ "data": { "downvotePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 4, "version": 12 } } }
设置 DdeletePost 解析程序 (DynamoDB DeleteItem)
接下来您要设置的更改是删除一个文章。要实现此目的,需要使用DeleteItem
DynamoDB 操作。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Mutation
类型,添加新的deletePost
更改,如下所示:type Mutation { deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
这次您将
expectedVersion
字段设为可选,稍后在添加请求映射模板时将对此进行说明。 -
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的删除字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "DeleteItem", "key": { "id": $util.dynamodb.toDynamoDBJson($context.arguments.id) } #if( $context.arguments.containsKey("expectedVersion") ) ,"condition" : { "expression" : "attribute_not_exists(id) OR version = :expectedVersion", "expressionValues" : { ":expectedVersion" : $util.dynamodb.toDynamoDBJson($context.arguments.expectedVersion) } } #end }
注意:这些区域有:
expectedVersion
参数是可选的。如果来电者设置了expectedVersion
请求中的参数,模板添加了一个条件,该条件只允许DeleteItem
如果项目已被删除或者version
DynamoDB 中帖子的属性完全匹配expectedVersion
. 如果未设置此参数,则DeleteItem
请求中不指定条件表达式。无论其价值如何,它都会成功version
DynamoDB 中是否存在该项目。 -
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
注意:即使您要删除一个项目,如果该项目不是已经删除,还是可以返回要删除的项目。
-
选择保存。
有关 DeleteItem
请求映射的更多信息,请参阅 DeleteItem 参考文档。
调用 API 以删除文章
现在解析器已经设置好了,AmazonAppSync 知道如何翻译来电delete
DynamoDB 的突变DeleteItem
operation. 现在,您可以运行更改,从表中删除一些内容。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation deletePost { deletePost(id:123) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
文章已经从 DynamoDB 中删除。请注意AmazonAppSync 返回已从 DynamoDB 中删除的项目的值,该项目应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "deletePost": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 4, "version": 12 } } }
只有调用的 deletePost
将项目从 DynamoDB 中实际删除,才会返回值。
-
再次选择 Execute query (执行查询)。
-
调用仍是成功的,但没有返回值。
{ "data": { "deletePost": null } }
现在让我们尝试删除一篇文章,但这次要指定 expectedValue
。但首先您需要创建一个新文章,因为您刚刚删除了一直在使用的文章。
-
在 Queries (查询) 窗格中,粘贴以下更改:
mutation addPost { addPost( id:123 author: "AUTHORNAME" title: "Our second post!" content: "A new post." url: "https://aws.amazon.com/appsync/" ) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
新创建的文章的结果应出现在查询窗格右侧的结果窗格中。记下新建对象的
id
,因为一会您将用到它。如下所示:{ "data": { "addPost": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }
现在让我们尝试删除这个文章,但放入 expectedVersion
的错误值:
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation deletePost { deletePost( id:123 expectedVersion: 9999 ) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
{ "data": { "deletePost": null }, "errors": [ { "path": [ "deletePost" ], "data": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 }, "errorType": "DynamoDB:ConditionalCheckFailedException", "locations": [ { "line": 2, "column": 3 } ], "message": "The conditional request failed (Service: AmazonDynamoDBv2; Status Code: 400; Error Code: ConditionalCheckFailedException; Request ID: ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ)" } ] }
请求失败,因为条件表达式评估为 false:
version
DynamoDB 中的帖子与expectedValue
在参数中指定。对象的当前值返回到 GraphQL 响应的data
部分的errors
字段中。 -
重试请求,但更正
expectedVersion
:mutation deletePost { deletePost( id:123 expectedVersion: 1 ) { id author title content url ups downs version } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
这次请求成功,而且返回了从 DynamoDB 中删除的值:
{ "data": { "deletePost": { "id": "123", "author": "AUTHORNAME", "title": "Our second post!", "content": "A new post.", "url": "https://aws.amazon.com/appsync/", "ups": 1, "downs": 0, "version": 1 } } }
-
再次选择 Execute query (执行查询)。
-
调用仍是成功的,但这次没有返回值,因为 DynamoDB 中的文章已被删除。
{ "data": { "deletePost": null } }
设置 allPost 解析程序 (DynamoDB Scan)
到目前为止,只有当您知道您想查看的每个帖子的 id
时,API 才有用。让我们添加新的解析程序,它可以返回表中的所有文章。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Query
类型,添加新的allPost
查询,如下所示:type Query { allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
-
添加新
PaginationPosts
类型:type PaginatedPosts { posts: [Post!]! nextToken: String }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的allPost字段中的查询键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "Scan" #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end }
此解析程序有两个可选参数:
count
指定单次调用可返回的项目数量上限;nextToken
可用于检索下一组结果(稍后您将展示nextToken
的值来自何处)。 -
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }
注意:到目前为止,此响应映射模板与所有其他模板均不同。
allPost
查询的结果是PaginatedPosts
,其中包含一组文章和一个分页标记。此对象的形状与从AmazonAppSync DynamoDB 解析器:帖子列表称为items
中的AmazonAppSync DynamoDB 解析器结果,但被称为posts
在PaginatedPosts
. -
选择保存。
有关 Scan
请求映射的更多信息,请参阅 Scan 参考文档。
调用 API 以扫描所有文章
现在解析器已经设置好了,AmazonAppSync 知道如何翻译来电allPost
查询 DynamoDBScan
operation. 现在您可以扫描整个表,检索所有文章。
在进行尝试之前,您需要在表中填充一些数据,因为您已经删除了之前使用的所有内容。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改:
mutation addPost { post1: addPost(id:1 author: "AUTHORNAME" title: "A series of posts, Volume 1" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post2: addPost(id:2 author: "AUTHORNAME" title: "A series of posts, Volume 2" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post3: addPost(id:3 author: "AUTHORNAME" title: "A series of posts, Volume 3" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post4: addPost(id:4 author: "AUTHORNAME" title: "A series of posts, Volume 4" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post5: addPost(id:5 author: "AUTHORNAME" title: "A series of posts, Volume 5" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post6: addPost(id:6 author: "AUTHORNAME" title: "A series of posts, Volume 6" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post7: addPost(id:7 author: "AUTHORNAME" title: "A series of posts, Volume 7" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post8: addPost(id:8 author: "AUTHORNAME" title: "A series of posts, Volume 8" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } post9: addPost(id:9 author: "AUTHORNAME" title: "A series of posts, Volume 9" content: "Some content" url: "https://aws.amazon.com/appsync/" ) { title } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
现在,让我们扫描表,每次返回 5 个结果。
-
在Queries (查询) 窗格中粘贴以下查询:
query allPost { allPost(count: 5) { posts { id title } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
最前面的 5 个文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "allPost": { "posts": [ { "id": "5", "title": "A series of posts, Volume 5" }, { "id": "1", "title": "A series of posts, Volume 1" }, { "id": "6", "title": "A series of posts, Volume 6" }, { "id": "9", "title": "A series of posts, Volume 9" }, { "id": "7", "title": "A series of posts, Volume 7" } ], "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRkJEdXdUK09hcnovRGhNTGxLTGdMUEFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF6ajFodkhKU1paT1pncTRaUUNBUkNBZ2dHWnJiR1dQWGxkMDB1N0xEdGY4Z2JsbktzRjRua1VCcks3TFJLcjZBTFRMeGFwVGJZMDRqOTdKVFQyYVRwSzdzbVdtNlhWWFVCTnFIOThZTzBWZHVkdDI2RlkxMHRqMDJ2QTlyNWJTUWpTbWh6NE5UclhUMG9KZWJSQ2JJbXBlaDRSVlg0Tis0WTVCN1IwNmJQWWQzOVhsbTlUTjBkZkFYMVErVCthaXZoNE5jMk50RitxVmU3SlJ5WmpzMEFkSGduM3FWd2VrOW5oeFVVd3JlK1loUks5QkRzemdiMDlmZmFPVXpzaFZ4cVJRbC93RURlOTcrRmVJdXZNby9NZ1F6dUdNbFRyalpNR3FuYzZBRnhwa0VlZTFtR0FwVDFISElUZlluakptYklmMGUzUmcxbVlnVHVSbDh4S0trNmR0QVoraEhLVDhuNUI3VnF4bHRtSnlNUXBrZGl6KzkyL3VzNDl4OWhrMnVxSW01ZFFwMjRLNnF0dm9ZK1BpdERuQTc5djhzb0grVytYT3VuQ2NVVDY4TVZ1Wk5KYkRuSEFSSEVlaTlVNVBTelU5RGZ6d2pPdmhqWDNJMWhwdWUrWi83MDVHVjlPQUxSTGlwZWZPeTFOZFhwZTdHRDZnQW00bUJUK2c1eC9Ec3ZDbWVnSDFDVXRTdHVuU1ZFa2JpZytQRC9oMUwyRTNqSHhVQldaa28yU256WUc0cG0vV1RSWkFVZHZuQT09In0=" } } }
您可以看到 5 个结果,还有一个 nextToken
,可用于获得下一组结果。
-
更新
allPost
查询,加入上一组结果的nextToken
:query allPost { allPost( count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnRlluNktJRWl6V0ZlR3hJOVJkaStrZUFBQUI1akNDQWVJR0NTcUdTSWIzRFFFSEJxQ0NBZE13Z2dIUEFnRUFNSUlCeUFZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5cW8yUGFSZThnalFpemRCTUNBUkNBZ2dHWk1JODhUNzhIOFVUZGtpdFM2ZFluSWRyVDg4c2lkN1RjZzB2d1k3VGJTTWpSQ2U3WjY3TkUvU2I1dWNETUdDMmdmMHErSGJSL0pteGRzYzVEYnE1K3BmWEtBdU5jSENJdWNIUkJ0UHBPWVdWdCtsS2U5L1pNcWdocXhrem1RaXI1YnIvQkt6dU5hZmJCdE93NmtoM2Jna1BKM0RjWWhpMFBGbmhMVGg4TUVGSjBCcXg3RTlHR1V5N0tUS0JLZlV3RjFQZ0JRREdrNzFYQnFMK2R1S2IrVGtZZzVYMjFrc3NyQmFVTmNXZmhTeXE0ZUJHSWhqZWQ5c3VKWjBSSTc2ZnVQdlZkR3FLNENjQmxHYXhpekZnK2pKK1FneEU1SXduRTNYYU5TR0I4QUpmamR2bU1wbUk1SEdvWjlMUUswclczbG14RDRtMlBsaTNLaEVlcm9pem5zcmdINFpvcXIrN2ltRDN3QkJNd3BLbGQzNjV5Nnc4ZnMrK2FnbTFVOUlKOFFrOGd2bEgySHFROHZrZXBrMWlLdWRIQ25LaS9USnBlMk9JeEVPazVnRFlzRTRUU09HUlVJTkxYY2MvdW1WVEpBMUthV2hWTlAvdjNlSnlZQUszbWV6N2h5WHVXZ1BkTVBNWERQdTdjVnVRa3EwK3NhbGZOd2wvSUx4bHNyNDVwTEhuVFpyRWZvVlV1bXZ5S2VKY1RUU1lET05hM1NwWEd2UT09In0=" ) { posts { id author } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
其余的 4 个文章应出现在查询窗格右侧的结果窗格中。在这一组结果中没有
nextToken
,因为您已经找到了所有的 9 个文章,没有其他内容了。如下所示:{ "data": { "allPost": { "posts": [ { "id": "2", "title": "A series of posts, Volume 2" }, { "id": "3", "title": "A series of posts, Volume 3" }, { "id": "4", "title": "A series of posts, Volume 4" }, { "id": "8", "title": "A series of posts, Volume 8" } ], "nextToken": null } } }
设置 allPostsByAuthor 解析程序 (DynamoDB 查询)
除了可以扫描 DynamoDB 中的所有文章,您还可以查询 DynamoDB,检索由特定作者创建的文章。您之前创建的 DynamoDB 表已有一个GlobalSecondaryIndex
叫author-index
你可以与 DynamoDB 一起使用Query
操作,检索由特定作者创建的所有文章。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Query
类型,添加新的allPostsByAuthor
查询,如下所示:type Query { allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
注意:这使用相同的
PaginatedPosts
键入您与allPost
查询。 -
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的allPostsByAuthor字段中的查询键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "Query", "index" : "author-index", "query" : { "expression": "author = :author", "expressionValues" : { ":author" : $util.dynamodb.toDynamoDBJson($context.arguments.author) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": "${context.arguments.nextToken}" #end }
与
allPost
解析程序相似,此解析程序也有两个可选参数:count
指定单次调用可返回的项目数量上限;nextToken
可用于检索下一组结果(nextToken
的值可从上次调用获得)。 -
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }
注意:这与您在中使用的响应映射模板相同。
allPost
解析器。 -
选择保存。
了解有关 Query
请求映射的更多信息,请参阅 Query 参考文档。
调用 API 以查询某一作者的所有文章
现在解析器已经设置好了,AmazonAppSync 知道如何翻译来电allPostsByAuthor
DynamoDB 的突变Query
针对author-index
索引。现在,您可以查询表,检索某一作者的所有文章。
但首先我们需要在表中再填充一些文章,因为目前所有文章都是同一作者。
-
选择 Queries 选项卡。
-
在 Queries (查询) 窗格中,粘贴以下更改:
mutation addPost { post1: addPost(id:10 author: "Nadia" title: "The cutest dog in the world" content: "So cute. So very, very cute." url: "https://aws.amazon.com/appsync/" ) { author, title } post2: addPost(id:11 author: "Nadia" title: "Did you know...?" content: "AppSync works offline?" url: "https://aws.amazon.com/appsync/" ) { author, title } post3: addPost(id:12 author: "Steve" title: "I like GraphQL" content: "It's great" url: "https://aws.amazon.com/appsync/" ) { author, title } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
现在,让我们查询表,返回作者为 Nadia
的所有文章。
-
在Queries (查询) 窗格中粘贴以下查询:
query allPostsByAuthor { allPostsByAuthor(author: "Nadia") { posts { id title } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
作者为
Nadia
的全部文章应出现在查询窗格右侧的结果窗格中。如下所示:{ "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you know...?" } ], "nextToken": null } } }
Query
的分页方式与 Scan
相同。例如,如果我们查找作者为 AUTHORNAME
的所有文章,每次显示 5 个结果。
-
在Queries (查询) 窗格中粘贴以下查询:
query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 ) { posts { id title } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
作者为
AUTHORNAME
的全部文章应出现在查询窗格右侧的结果窗格中。如下所示:{ "data": { "allPostsByAuthor": { "posts": [ { "id": "6", "title": "A series of posts, Volume 6" }, { "id": "4", "title": "A series of posts, Volume 4" }, { "id": "2", "title": "A series of posts, Volume 2" }, { "id": "7", "title": "A series of posts, Volume 7" }, { "id": "1", "title": "A series of posts, Volume 1" } ], "nextToken": "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" } } }
-
用上次查询返回的值更新
nextToken
参数,如下所示:query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" count: 5 nextToken: "eyJ2ZXJzaW9uIjoxLCJ0b2tlbiI6IkFRSUNBSGo4eHR0RG0xWXhUa1F0cEhXMEp1R3B0M1B3eThOSmRvcG9ad2RHYjI3Z0lnSExqRnVhVUR3ZUhEZ2QzNGJ2QlFuY0FBQUNqekNDQW9zR0NTcUdTSWIzRFFFSEJxQ0NBbnd3Z2dKNEFnRUFNSUlDY1FZSktvWklodmNOQVFjQk1CNEdDV0NHU0FGbEF3UUJMakFSQkF5Qkg4Yk1obW9LVEFTZHM3SUNBUkNBZ2dKQ3dISzZKNlJuN3pyYUVKY1pWNWxhSkNtZW1KZ0F5N1dhZkc2UEdTNHpNQzJycTkwZHFJTFV6Z25wck9Gd3pMS3VOQ2JvUXc3VDI5eCtnVExIbGg4S3BqbzB1YjZHQ3FwcDhvNDVmMG9JbDlmdS9JdjNXcFNNSXFKTXZ1MEVGVWs1VzJQaW5jZGlUaVRtZFdYWlU1bkV2NkgyRFBRQWZYYlNnSmlHSHFLbmJZTUZZM0FTdmRIL0hQaVZBb1RCMk1YZkg0eGJOVTdEbjZtRFNhb2QwbzdHZHJEWDNtODQ1UXBQUVNyUFhHemY0WDkyajhIdlBCSWE4Smcrb0RxbHozUVQ5N2FXUXdYWWU2S0h4emI1ejRITXdEdXEyRDRkYzhoMi9CbW10MzRMelVGUVIyaExSZGRaZ0xkdzF5cHJZdFZwY3dEc1d4UURBTzdOcjV2ZEp4VVR2TVhmODBRSnp1REhXREpTVlJLdDJwWmlpaXhXeGRwRmNod1BzQ3d2aVBqMGwrcWFFWU1jMXNQbENkVkFGem43VXJrSThWbS8wWHlwR2xZb3BSL2FkV0xVekgrbGMrYno1ZEM2SnVLVXdtY1EyRXlZeDZiS0Izbi9YdUViWGdFeU5PMWZTdE1rRlhyWmpvMVpzdlYyUFRjMzMrdEs0ZDhkNkZrdjh5VVR6WHhJRkxIaVNsOUx6VVdtT3BCaWhrTFBCT09jcXkyOHh1UmkzOEM3UFRqMmN6c3RkOUo1VUY0azBJdUdEbVZzM2xjdWg1SEJjYThIeXM2aEpvOG1HbFpMNWN6R2s5bi8vRE1EbDY3RlJraG5QNFNhSDBpZGI5VFEvMERLeFRBTUdhcWpPaEl5ekVqd2ZDQVJleFdlbldyOGlPVkhScDhGM25WZVdvbFRGK002N0xpdi9XNGJXdDk0VEg3b0laUU5lYmZYKzVOKy9Td25Hb1dyMTlWK0pEb2lIRVFLZ1cwMWVuYjZKUXo5Slh2Tm95ZzF3RnJPVmxGc2xwNlRHa1BlN2Rnd2IrWT0ifQ==" ) { posts { id title } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
作者为
AUTHORNAME
的剩余文章应出现在查询窗格右侧的结果窗格中。如下所示:{ "data": { "allPostsByAuthor": { "posts": [ { "id": "8", "title": "A series of posts, Volume 8" }, { "id": "5", "title": "A series of posts, Volume 5" }, { "id": "3", "title": "A series of posts, Volume 3" }, { "id": "9", "title": "A series of posts, Volume 9" } ], "nextToken": null } } }
使用集
到目前为止,Post
类型一直是平面的键/值对象。您还可以使用AmazonAppSyncDynamoDB 解析程序,例如集、列表和映射。
让我们更新 Post
类型,加入标签。一个文章可以没有标签,也可以有多个标签;标签作为字符串集存储在 DynamoDB 中。您还将设置一些更改,用于添加并删除标签;还要用一个新查询扫描具有特定标签的文章。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中修改
Post
类型,添加新的tags
字段,如下所示:type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] }
-
在 Schema (架构) 窗格中修改
Query
类型,添加新的allPostsByTag
查询,如下所示:type Query { allPostsByTag(tag: String!, count: Int, nextToken: String): PaginatedPosts! allPostsByAuthor(author: String!, count: Int, nextToken: String): PaginatedPosts! allPost(count: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
-
在 Schema (架构) 窗格中修改
Mutation
类型,添加新的addTag
和removeTag
更改,如下所示:type Mutation { addTag(id: ID!, tag: String!): Post removeTag(id: ID!, tag: String!): Post deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的allPostsByTag字段中的查询键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "Scan", "filter": { "expression": "contains (tags, :tag)", "expressionValues": { ":tag": $util.dynamodb.toDynamoDBJson($context.arguments.tag) } } #if( ${context.arguments.count} ) ,"limit": $util.toJson($context.arguments.count) #end #if( ${context.arguments.nextToken} ) ,"nextToken": $util.toJson($context.arguments.nextToken) #end }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
{ "posts": $utils.toJson($context.result.items) #if( ${context.result.nextToken} ) ,"nextToken": $util.toJson($context.result.nextToken) #end }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的AddTag字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "ADD tags :tags, version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的RremoveTag字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "DELETE tags :tags ADD version :plusOne", "expressionValues" : { ":tags" : { "SS": [ $util.toJson($context.arguments.tag) ] }, ":plusOne" : { "N" : 1 } } } }
-
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
调用 API 以处理标签
现在您已设置解析程序,AmazonAppSync 知道如何翻译来电addTag
、removeTag
, 和allPostsByTag
对 DynamoDB 的请求UpdateItem
和Scan
操作。
我们选择您之前创建的一个文章进行尝试。例如,我们使用作者为 Nadia
的一篇文章。
-
选择 Queries 选项卡。
-
在Queries (查询) 窗格中粘贴以下查询:
query allPostsByAuthor { allPostsByAuthor( author: "Nadia" ) { posts { id title } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
Nadia 的全部文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you known...?" } ], "nextToken": null } } }
-
让我们使用标题为
"The cutest dog in the world"
的文章。记下其id
,因为您稍后将用到它。
现在,让我们尝试添加 dog
标签。
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation addTag { addTag(id:10 tag: "dog") { id title tags } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
文章已更新,添加了这个新标签。
{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
您可以添加更多标签,如下所示:
-
更新更改,将
tag
参数改为puppy
。mutation addTag { addTag(id:10 tag: "puppy") { id title tags } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
文章已更新,添加了这个新标签。
{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } } }
您也可以删除标签:
-
在 Queries (查询) 窗格中,粘贴以下更改。您还需要更新
id
参数,改为您之前记下的值。mutation removeTag { removeTag(id:10 tag: "puppy") { id title tags } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
文章已更新,
puppy
标签已删除。{ "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
您也可以搜索具有某一标签的所有文章:
-
在Queries (查询) 窗格中粘贴以下查询:
query allPostsByTag { allPostsByTag(tag: "dog") { posts { id title tags } nextToken } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
将返回具有
dog
标签的所有文章,如下所示:{ "data": { "allPostsByTag": { "posts": [ { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } ], "nextToken": null } } }
使用列表和映射
您不仅可以使用 DynamoDB 集,还可以使用 DynamoDB 列表和映射,在单独的对象中建模复杂的数据。
我们可以为文章添加评论功能。在中,该功能作为映射列表对象进行建模。Post
DynamoDB 中的对象。
注意:在真正的应用程序中,您会在评论自身的表中对评论进行建模。在本教程中,您仅将评论添加到 Post
表。
-
选择 Schema (架构) 选项卡。
-
在 Schema (架构) 窗格中,添加新的
Comment
类型,如下所示:type Comment { author: String! comment: String! }
-
在 Schema (架构) 窗格中修改
Post
类型,添加新的comments
字段,如下所示:type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] comments: [Comment!] }
-
在 Schema (架构) 窗格中修改
Mutation
类型,添加新的addComment
更改,如下所示:type Mutation { addComment(id: ID!, author: String!, comment: String!): Post addTag(id: ID!, tag: String!): Post removeTag(id: ID!, tag: String!): Post deletePost(id: ID!, expectedVersion: Int): Post upvotePost(id: ID!): Post downvotePost(id: ID!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( author: String!, title: String!, content: String!, url: String! ): Post! }
-
选择保存。
-
在数据类型在右侧的窗格中,找到新创建的AddComment字段中的更改键入,然后选择Attach.
-
在 Data source name (数据源名称) 中,选择 PostDynamoDBTable。
-
在 Configure the request mapping template (配置请求映射模板) 中,粘贴以下内容:
{ "version" : "2017-02-28", "operation" : "UpdateItem", "key" : { "id" : $util.dynamodb.toDynamoDBJson($context.arguments.id) }, "update" : { "expression" : "SET comments = list_append(if_not_exists(comments, :emptyList), :newComment) ADD version :plusOne", "expressionValues" : { ":emptyList": { "L" : [] }, ":newComment" : { "L" : [ { "M": { "author": $util.dynamodb.toDynamoDBJson($context.arguments.author), "comment": $util.dynamodb.toDynamoDBJson($context.arguments.comment) } } ] }, ":plusOne" : $util.dynamodb.toDynamoDBJson(1) } } }
此更新表达式将一个列表(包含新评论)追加到现有的
comments
列表中。如果这个列表不存在,将创建它。 -
在 Configure the response mapping template (配置响应映射模板) 中,粘贴以下内容:
$utils.toJson($context.result)
-
选择保存。
调用 API 以添加评论
现在您已设置解析程序,AmazonAppSync 知道如何翻译来电addComment
对 DynamoDB 的请求UpdateItem
操作。
让我们尝试在您已添加标签的文章中添加评论。
-
选择 Queries 选项卡。
-
在Queries (查询) 窗格中粘贴以下查询:
mutation addComment { addComment( id:10 author: "Steve" comment: "Such a cute dog." ) { id comments { author comment } } }
-
选择 Execute query (执行查询)(橙色播放按钮)。
-
Nadia 的全部文章应出现在查询窗格右侧的结果窗格中。如下所示:
{ "data": { "addComment": { "id": "10", "comments": [ { "author": "Steve", "comment": "Such a cute dog." } ] } } }
如果您多次执行该请求,列表中将追加多条评论。
结论
在本教程中,您构建了 API,使用AmazonAppSync 和 GraphQL。有关更多信息,请参阅解析程序映射模板参考。
要进行清理,您可以从控制台中删除 AppSync GraphQL API。
要删除 DynamoDB 表以及您为本教程创建的 IAM 角色,您可以运行以下代码删除AWSAppSyncTutorialForAmazonDynamoDB
堆叠,或者访问Amazon CloudFormation控制台并删除堆栈:
aws cloudformation delete-stack \ --stack-name AWSAppSyncTutorialForAmazonDynamoDB