教程:DynamoDB JavaScript 解析器 - Amazon AppSync
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

教程:DynamoDB JavaScript 解析器

在本教程中,您将 Amazon DynamoDB 表导入到 Amazon AppSync,并连接这些表以使用 JavaScript 管道解析器构建功能齐全的 GraphQL API,您可以在自己的应用程序中使用该 API。

您将使用 Amazon AppSync 控制台预置 Amazon DynamoDB 资源,创建解析器并将其连接到您的数据源。您也可以通过 GraphQL 语句读取和写入 Amazon DynamoDB 数据库并订阅实时数据。

必须完成一些特定的步骤,才能将 GraphQL 语句转换为 Amazon DynamoDB 操作以及将响应转换回 GraphQL。本教程通过一些现实世界的场景和数据访问模式介绍了配置过程。

创建您的 GraphQL API

在 Amazon AppSync 中创建 GraphQL API

  1. 打开 AppSync 控制台,然后选择创建 API

  2. 选择从头开始设计,然后选择下一步

  3. 将您的 API 命名为 PostTutorialAPI,然后选择下一步。跳到检查页面,同时将其余选项设置为默认值,然后选择Create

Amazon AppSync 控制台将为您创建一个新的 GraphQL API。默认情况下,它使用 API 密钥身份验证方式。您可以根据本教程后面的说明,使用控制台设置 GraphQL API 的其余部分,并针对它运行查询。

定义基本文章 API

您现在具有 GraphQL API,您可以设置一个基本架构,以允许对文章数据执行基本创建、检索和删除操作。

将数据添加到您的架构

  1. 在您的 API 中,选择架构选项卡。

  2. 我们将创建一个架构,它定义 Post 类型和 addPost 操作以添加和获取 Post 对象。在架构窗格中,将内容替换为以下代码:

    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! }
  3. 选择 Save Schema (保存架构)

设置您的 Amazon DynamoDB 表

Amazon AppSync 控制台可以帮助预置在 Amazon DynamoDB 表中存储您自己的资源所需的 Amazon 资源。在该步骤中,您创建一个 Amazon DynamoDB 表以存储您的文章。您还会设置我们稍后使用的二级索引

创建您的 Amazon DynamoDB 表

  1. 架构页面上,选择创建资源

  2. 选择使用现有的类型,然后选择 Post 类型。

  3. 其他索引部分中,选择添加索引

  4. 将索引命名为 author-index

  5. Primary key 设置为 author,并将 Sort 键设置为 None

  6. 禁用自动生成 GraphQL。在该示例中,我们将自行创建解析器。

  7. 选择创建

您现在具有一个名为 PostTable 的新数据源,您可以访问侧面选项卡中的数据源以查看该数据源。您使用该数据源将查询和变更链接到 Amazon DynamoDB 表。

设置 addPost 解析器 (Amazon DynamoDB PutItem)

现在 Amazon AppSync 识别了 Amazon DynamoDB 表,您可以定义解析器以将其链接到各个查询和变更。您创建的第一个解析器使用 JavaScript 的 addPost 管道解析器,可用于在 Amazon DynamoDB 表中创建文章。管道解析器具有以下组件:

  • GraphQL 架构中的位置,用于附加解析器。在本例中,您将设置 createPost 类型的 Mutation 字段的解析器。在调用方调用 { addPost(...){...} } 变更时,将调用该解析器。

  • 此解析器所用的数据源。在该示例中,您希望使用以前定义的 DynamoDB 数据源,因此,您可以在 post-table-for-tutorial DynamoDB 表中添加条目。

  • 请求处理程序。请求处理程序是一个函数,用于处理来自调用方的传入请求,并将其转换为 Amazon AppSync 指令以对 DynamoDB 执行。

  • 响应处理程序。响应处理程序的任务是,处理来自 DynamoDB 的响应,并将其转换回 GraphQL 所需的内容。如果 DynamoDB 中的数据形态与 GraphQL 中的 Post 类型不同,此模板很有用。但在此例中它们的形态相同,所以只用于传递数据。

设置您的解析器

  1. 在您的 API 中,选择架构选项卡。

  2. 解析器窗格中,找到 Mutation 类型下面的 addPost 字段,然后选择附加

  3. 选择您的数据源,然后选择创建

  4. 在代码编辑器中,将代码替换为以下代码片段:

    import { util } from '@aws-appsync/utils' import * as ddb from '@aws-appsync/utils/dynamodb' export function request(ctx) { const item = { ...ctx.arguments, ups: 1, downs: 0, version: 1 } const key = { id: ctx.args.id ?? util.autoId() } return ddb.put({ key, item }) } export function response(ctx) { return ctx.result }
  5. 选择保存

注意

在该代码中,您使用 DynamoDB 模块实用程序轻松创建 DynamoDB 请求。

Amazon AppSync 附带一个名为 util.autoId() 的自动 ID 生成实用程序,用于为您的新文章生成 ID。如果您未指定 ID,该实用程序将自动为您生成 ID。

const key = { id: ctx.args.id ?? util.autoId() }

有关适用于 JavaScript 的实用程序的更多信息,请参阅解析器和函数的 JavaScript 运行时功能

调用 API 以添加文章

解析器现已配置完毕,Amazon AppSync 可以将传入的 addPost 变更转换为 Amazon DynamoDB PutItem 操作。现在,您可以运行一个变更,在表中添加内容。

运行操作

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更:

    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 } }
  3. 选择运行(橙色播放按钮),然后选择 addPost。新创建的文章的结果应显示在查询窗格右侧的结果窗格中。如下所示:

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

以下解释说明了发生的情况:

  1. Amazon AppSync 收到 addPost 变更请求。

  2. Amazon AppSync 执行解析器的请求处理程序。ddb.put 函数创建一个 PutItem 请求,如下所示:

    { operation: 'PutItem', key: { id: { S: '123' } }, attributeValues: { downs: { N: 0 }, author: { S: 'AUTHORNAME' }, ups: { N: 1 }, title: { S: 'Our first post!' }, version: { N: 1 }, content: { S: 'This is our first post.' }, url: { S: 'https://aws.amazon.com/appsync/' } } }
  3. Amazon AppSync 使用该值生成并执行 Amazon DynamoDB PutItem 请求。

  4. Amazon AppSync 将 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 }
  5. 响应处理程序立即返回结果 (return ctx.result)。

  6. 最终结果显示在 GraphQL 响应中。

设置 getPost 解析器 (Amazon DynamoDB GetItem)

您现在能够将数据添加到 Amazon DynamoDB 表中,您需要设置 getPost 查询,以使其可以从表中检索该数据。为了实现此目的,您要设置另一解析器。

添加您的解析器

  1. 在您的 API 中,选择架构选项卡。

  2. 在右侧的解析器窗格中,找到 Query 类型上的 getPost 字段,然后选择附加

  3. 选择您的数据源,然后选择创建

  4. 在代码编辑器中,将代码替换为以下代码片段:

    import * as ddb from '@aws-appsync/utils/dynamodb' export function request(ctx) { return ddb.get({ key: { id: ctx.args.id } }) } export const response = (ctx) => ctx.result
  5. 保存解析器。

注意

在该解析器中,我们将箭头函数表达式用于响应处理程序。

调用 API 以获取文章

解析器现已设置完毕,Amazon AppSync 知道如何将传入的 getPost 查询转换为 Amazon DynamoDB GetItem 操作。现在,您可以运行查询,检索之前创建的文章。

运行您的查询

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下代码,并使用您在创建文章后复制的 ID:

    query getPost { getPost(id: "123") { id author title content url ups downs version } }
  3. 选择运行(橙色播放按钮),然后选择 getPost。新创建的文章的结果应显示在查询窗格右侧的结果窗格中。

  4. 从 Amazon 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 } } }

或者,采用以下示例:

query getPost { getPost(id: "123") { id author title } }

如果您的 getPost 查询仅需要 idauthortitle,您可以将请求函数更改为使用投影表达式仅指定您希望从 DynamoDB 表中获取的属性,以避免将不必要的数据从 DynamoDB 传输到 Amazon AppSync。例如,请求函数可能类似于以下代码片段:

import * as ddb from '@aws-appsync/utils/dynamodb' export function request(ctx) { return ddb.get({ key: { id: ctx.args.id }, projection: ['author', 'id', 'title'], }) } export const response = (ctx) => ctx.result

您也可以使用具有 getPostselectionSetList 以表示 expression

import * as ddb from '@aws-appsync/utils/dynamodb' export function request(ctx) { const projection = ctx.info.selectionSetList.map((field) => field.replace('/', '.')) return ddb.get({ key: { id: ctx.args.id }, projection }) } export const response = (ctx) => ctx.result

创建 updatePost 变更 (Amazon DynamoDB UpdateItem)

到目前为止,您可以在 Amazon DynamoDB 中创建和检索 Post 对象。接下来,您设置一个新的变更以更新对象。与需要指定所有字段的 addPost 变更相比,该变更允许您仅指定要更改的字段。它还引入一个新的 expectedVersion 参数,以允许您指定要修改的版本。您设置一个条件,以确保您修改对象的最新版本。您将使用 UpdateItem Amazon DynamoDB 操作完成该操作。

更新您的解析器

  1. 在您的 API 中,选择架构选项卡。

  2. Schema (架构) 窗格中修改 Mutation 类型,添加新的 updatePost 变更,如下所示:

    type Mutation { updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( id: ID author: String! title: String! content: String! url: String! ): Post! }
  3. 选择 Save Schema (保存架构)

  4. 在右侧的解析器窗格中,找到 Mutation 类型上的新创建的 updatePost 字段,然后选择附加。使用下面的代码片段创建新的解析器:

    import { util } from '@aws-appsync/utils'; import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { id, expectedVersion, ...rest } = ctx.args; const values = Object.entries(rest).reduce((obj, [key, value]) => { obj[key] = value ?? ddb.operations.remove(); return obj; }, {}); return ddb.update({ key: { id }, condition: { version: { eq: expectedVersion } }, update: { ...values, version: ddb.operations.increment(1) }, }); } export function response(ctx) { const { error, result } = ctx; if (error) { util.appendError(error.message, error.type); } return result;
  5. 保存您所做的任何更改。

该解析器使用 ddb.update 创建 Amazon DynamoDB UpdateItem 请求。您仅要求 Amazon DynamoDB 更新某些属性,而不是编写整个项目。这是使用 Amazon DynamoDB 更新表达式完成的。

ddb.update 函数将一个键和更新对象作为参数。然后,您检查传入的参数的值。在一个值设置为 null 时,使用 DynamoDB remove 操作指示应从 DynamoDB 项目中删除该值。

还有一个新的 condition 部分。通过使用条件表达式,您可以在执行操作之前根据 Amazon DynamoDB 中的已有对象的状态向 Amazon AppSync 和 Amazon DynamoDB 通知请求是否会成功。在该示例中,只有在当前位于 Amazon DynamoDB 中的项目的 version 字段与 expectedVersion 参数完全匹配时,您才希望 UpdateItem 请求成功。在更新项目时,我们希望增加 version 的值。可以使用 increment 操作函数轻松完成该操作。

有关条件表达式的更多信息,请参阅条件表达式文档。

有关 UpdateItem 请求的更多信息,请参阅 UpdateItem 文档和 DynamoDB 模块文档。

有关如何编写更新表达式的更多信息,请参阅 DynamoDB UpdateExpressions 文档

调用 API 以更新文章

让我们尝试使用新的解析器更新 Post 对象。

更新您的对象

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值:

    mutation updatePost { updatePost( id:123 title: "An empty story" content: null expectedVersion: 1 ) { id author title content url ups downs version } }
  3. 选择运行(橙色播放按钮),然后选择 updatePost

  4. 在 Amazon 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": 2 } } }

在该请求中,您要求 Amazon AppSync 和 Amazon DynamoDB 仅更新 titlecontent 字段。所有其他字段保持不变(除了递增 version 字段以外)。您将 title 属性设置为新的值,并从文章中删除 content 属性。authorurlupsdowns 字段没有变化。再次尝试执行变更请求,同时将请求完全保持原样。您可以看到类似以下内容的响应:

{ "data": { "updatePost": null }, "errors": [ { "path": [ "updatePost" ], "data": null, "errorType": "DynamoDB:ConditionalCheckFailedException", "errorInfo": null, "locations": [ { "line": 2, "column": 3, "sourceName": null } ], "message": "The conditional request failed (Service: DynamoDb, Status Code: 400, Request ID: 1RR3QN5F35CS8IV5VR4OQO9NNBVV4KQNSO5AEMVJF66Q9ASUAAJG)" } ] }

请求失败,因为条件表达式的评估结果为 false

  1. 第一次运行请求时,Amazon DynamoDB 中的文章的 version 字段值为 1,它与 expectedVersion 参数匹配。请求成功,这意味着 Amazon DynamoDB 中的 version 字段已增加到 2

  2. 第二次运行请求时,Amazon DynamoDB 中的文章的 version 字段值为 2,它与 expectedVersion 参数不匹配。

这种模式通常被称为乐观锁

创建评价变更 (Amazon DynamoDB UpdateItem)

Post 类型包含 upsdowns 字段,用于记录点赞和差评。不过,API 目前不允许我们进行任何评论。让我们添加一个变更,以对文章点赞和差评。

添加您的变更

  1. 在您的 API 中,选择架构选项卡。

  2. 架构窗格中,修改 Mutation 类型并添加 DIRECTION 枚举以添加新的评论变更:

    type Mutation { vote(id: ID!, direction: DIRECTION!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( id: ID, author: String!, title: String!, content: String!, url: String! ): Post! } enum DIRECTION { UP DOWN }
  3. 选择 Save Schema (保存架构)

  4. 在右侧的解析器窗格中,找到 Mutation 类型上的新创建的 vote 字段,然后选择附加。创建代码并将其替换为以下代码片段,以创建新的解析器:

    import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const field = ctx.args.direction === 'UP' ? 'ups' : 'downs'; return ddb.update({ key: { id: ctx.args.id }, update: { [field]: ddb.operations.increment(1), version: ddb.operations.increment(1), }, }); } export const response = (ctx) => ctx.result;
  5. 保存您所做的任何更改。

调用 API 以对文章点赞或差评

新的解析器现已设置完毕,Amazon AppSync 知道如何将传入的 upvotePostdownvote 变更转换为 Amazon DynamoDB UpdateItem 操作。现在您可以运行变更,为之前创建的文章点赞或差评。

运行您的变更

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值:

    mutation votePost { vote(id:123, direction: UP) { id author title content url ups downs version } }
  3. 选择运行(橙色播放按钮),然后选择 votePost

  4. 在 Amazon DynamoDB 中更新的文章应显示在查询窗格右侧的结果窗格中。如下所示:

    { "data": { "vote": { "id": "123", "author": "A new author", "title": "An empty story", "content": null, "url": "https://aws.amazon.com/appsync/", "ups": 6, "downs": 0, "version": 4 } } }
  5. 再选择几次运行。每次执行查询时,您应该会看到 upsversion 字段增加 1

  6. 更改查询以使用不同的 DIRECTION 进行调用。

    mutation votePost { vote(id:123, direction: DOWN) { id author title content url ups downs version } }
  7. 选择运行(橙色播放按钮),然后选择 votePost

    这次,每次运行查询时,您应该会看到 downsversion 字段增加 1

设置 deletePost 解析器 (Amazon DynamoDB DeleteItem)

接下来,您希望创建一个变更以删除文章。您将使用 DeleteItem Amazon DynamoDB 操作完成该操作。

添加您的变更

  1. 在您的架构中,选择架构选项卡。

  2. 架构窗格中,修改 Mutation 类型以添加新的 deletePost 变更:

    type Mutation { deletePost(id: ID!, expectedVersion: Int): Post vote(id: ID!, direction: DIRECTION!): Post updatePost( id: ID!, author: String, title: String, content: String, url: String, expectedVersion: Int! ): Post addPost( id: ID author: String!, title: String!, content: String!, url: String! ): Post! }
  3. 这次,您将 expectedVersion 字段设置为可选。接下来,选择保存架构

  4. 在右侧的解析器窗格中,找到 Mutation 类型中的新创建的 delete 字段,然后选择附加。使用以下代码创建一个新的解析器:

    import { util } from '@aws-appsync/utils' import { util } from '@aws-appsync/utils'; import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { let condition = null; if (ctx.args.expectedVersion) { condition = { or: [ { id: { attributeExists: false } }, { version: { eq: ctx.args.expectedVersion } }, ], }; } return ddb.remove({ key: { id: ctx.args.id }, condition }); } export function response(ctx) { const { error, result } = ctx; if (error) { util.appendError(error.message, error.type); } return result; }
    注意

    expectedVersion 参数是可选的参数。如果调用方在请求中设置 expectedVersion 参数,请求处理程序将添加一个条件,只有在已删除项目或 Amazon DynamoDB 中的文章的 version 属性与 expectedVersion 完全匹配时,才允许 DeleteItem 请求成功。如果未设置此参数,则 DeleteItem 请求中不指定条件表达式。无论 version 值如何,或者项目在 Amazon DynamoDB 中是否存在,该请求都会成功。

    即使您要删除一个项目,如果尚未删除,您也可以返回要删除的项目。

有关 DeleteItem 请求的更多信息,请参阅 DeleteItem 文档。

调用 API 以删除文章

解析器现已设置完毕,Amazon AppSync 知道如何将传入的 delete 变更转换为 Amazon DynamoDB DeleteItem 操作。现在,您可以运行变更,从表中删除一些内容。

运行您的变更

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值:

    mutation deletePost { deletePost(id:123) { id author title content url ups downs version } }
  3. 选择运行(橙色播放按钮),然后选择 deletePost

  4. 将从 Amazon DynamoDB 中删除该文章。请注意,Amazon AppSync 返回从 Amazon 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 } } }
  5. 只有在对 deletePost 的该调用实际将其从 Amazon DynamoDB 中删除时,才会返回该值。再次选择运行

  6. 调用仍然成功,但没有返回任何值:

    { "data": { "deletePost": null } }
  7. 现在,让我们尝试删除一篇文章,但这次指定 expectedValue。首先,您需要创建一个新文章,因为您刚刚删除了迄今为止一直使用的文章。

  8. 查询窗格中,添加以下变更:

    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 } }
  9. 选择运行(橙色播放按钮),然后选择 addPost

  10. 新创建的文章的结果应显示在查询窗格右侧的结果窗格中。记下新创建的对象的 id,因为您稍后需要使用该 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 } } }
  11. 现在,让我们尝试删除具有非法 expectedVersion 值的文章。在查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值:

    mutation deletePost { deletePost( id:123 expectedVersion: 9999 ) { id author title content url ups downs version } }
  12. 选择运行(橙色播放按钮),然后选择 deletePost。将返回以下结果:

    { "data": { "deletePost": null }, "errors": [ { "path": [ "deletePost" ], "data": null, "errorType": "DynamoDB:ConditionalCheckFailedException", "errorInfo": null, "locations": [ { "line": 2, "column": 3, "sourceName": null } ], "message": "The conditional request failed (Service: DynamoDb, Status Code: 400, Request ID: 7083O037M1FTFRK038A4CI9H43VV4KQNSO5AEMVJF66Q9ASUAAJG)" } ] }
  13. 请求失败,因为条件表达式的评估结果为 false。Amazon DynamoDB 中的文章 version 值与参数中指定的 expectedValue 不匹配。对象的当前值返回到 GraphQL 响应的 data 部分的 errors 字段中。重试请求,但更正 expectedVersion

    mutation deletePost { deletePost( id:123 expectedVersion: 1 ) { id author title content url ups downs version } }
  14. 选择运行(橙色播放按钮),然后选择 deletePost

    这次请求成功,并返回从 Amazon 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 } } }
  15. 再次选择运行。调用仍然成功,但这次没有返回任何值,因为已在 Amazon DynamoDB 中删除该文章。

    { "data": { "deletePost": null } }

设置 allPost 解析器 (Amazon DynamoDB Scan)

到目前为止,只有在您知道要查看的每篇文章的 id 时,才能使用该 API。让我们添加新的解析器,它可以返回表中的所有文章。

添加您的变更

  1. 在您的 API 中,选择架构选项卡。

  2. Schema (架构) 窗格中修改 Query 类型,添加新的 allPost 查询,如下所示:

    type Query { allPost(limit: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
  3. 添加新 PaginationPosts 类型:

    type PaginatedPosts { posts: [Post!]! nextToken: String }
  4. 选择 Save Schema (保存架构)

  5. 在右侧的解析器窗格中,找到 Query 类型中的新创建的 allPost 字段,然后选择附加。使用以下代码创建一个新的解析器:

    import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { limit = 20, nextToken } = ctx.arguments; return ddb.scan({ limit, nextToken }); } export function response(ctx) { const { items: posts = [], nextToken } = ctx.result; return { posts, nextToken }; }

    该解析器的请求处理程序需要使用两个可选的参数:

    • limit - 指定单次调用中返回的最大项目数。

    • nextToken - 用于检索下一组结果(我们稍后将显示 nextToken 值来自何处)。

  6. 保存对您的解析器所做的任何更改。

有关 Scan 请求的更多信息,请参阅 Scan 参考文档。

调用 API 以扫描所有文章

解析器现已设置完毕,Amazon AppSync 知道如何将传入的 allPost 查询转换为 Amazon DynamoDB Scan 操作。现在您可以扫描整个表,检索所有文章。在进行尝试之前,您需要在表中填充一些数据,因为您已经删除了之前使用的所有内容。

添加和查询数据

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更:

    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 } }
  3. 选择运行(橙色播放按钮)。

  4. 现在,让我们扫描表,每次返回 5 个结果。在查询窗格中,添加以下查询:

    query allPost { allPost(limit: 5) { posts { id title } nextToken } }
  5. 选择运行(橙色播放按钮),然后选择 allPost

    前 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": "<token>" } } }
  6. 您收到 5 个结果和一个 nextToken(可用于获取下一组结果)。更新 allPost 查询,加入上一组结果的 nextToken

    query allPost { allPost( limit: 5 nextToken: "<token>" ) { posts { id author } nextToken } }
  7. 选择运行(橙色播放按钮),然后选择 allPost

    其余 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 解析器 (Amazon DynamoDB Query)

除了扫描 Amazon DynamoDB 以查找所有文章以外,您还可以查询 Amazon DynamoDB 以检索特定作者创建的文章。您以前创建的 Amazon DynamoDB 表已具有一个名为 author-indexGlobalSecondaryIndex,您可以将其与 Amazon DynamoDB Query 操作一起使用以检索特定作者创建的所有文章。

添加您的查询

  1. 在您的 API 中,选择架构选项卡。

  2. Schema (架构) 窗格中修改 Query 类型,添加新的 allPostsByAuthor 查询,如下所示:

    type Query { allPostsByAuthor(author: String!, limit: Int, nextToken: String): PaginatedPosts! allPost(limit: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }

    请注意,它使用与 allPost 查询相同的 PaginatedPosts 类型。

  3. 选择 Save Schema (保存架构)

  4. 在右侧的解析器窗格中,找到 Query 类型上的新创建的 allPostsByAuthor 字段,然后选择附加。使用下面的代码片段创建一个解析器:

    import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { limit = 20, nextToken, author } = ctx.arguments; return ddb.query({ index: 'author-index', query: { author: { eq: author } }, limit, nextToken, }); } export function response(ctx) { const { items: posts = [], nextToken } = ctx.result; return { posts, nextToken }; }

    allPost 解析器一样,该解析器具有两个可选的参数:

    • limit - 指定单次调用中返回的最大项目数。

    • nextToken - 检索下一组结果(可以从以前的调用中获取 nextToken 值)。

  5. 保存对您的解析器所做的任何更改。

有关 Query 请求的更多信息,请参阅 Query 参考文档。

调用 API 以查询作者的所有文章

解析器现已设置完毕,Amazon AppSync 知道如何将传入的 allPostsByAuthor 变更转换为针对 author-index 索引的 DynamoDB Query 操作。现在,您可以查询表,检索某一作者的所有文章。

不过,在此之前,让我们在表中再填充一些文章,因为到目前为止每篇文章都是由同一作者撰写的。

添加数据和查询

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下变更:

    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 } }
  3. 选择运行(橙色播放按钮),然后选择 addPost

  4. 现在,让我们查询表,返回作者为 Nadia 的所有文章。在查询窗格中,添加以下查询:

    query allPostsByAuthor { allPostsByAuthor(author: "Nadia") { posts { id title } nextToken } }
  5. 选择运行(橙色播放按钮),然后选择 allPostsByAuthorNadia 撰写的所有文章应显示在查询窗格右侧的结果窗格中。如下所示:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you know...?" } ], "nextToken": null } } }
  6. Query 的分页方式与 Scan 相同。例如,如果我们查找作者为 AUTHORNAME 的所有文章,每次显示 5 个结果。

  7. 查询窗格中,添加以下查询:

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" limit: 5 ) { posts { id title } nextToken } }
  8. 选择运行(橙色播放按钮),然后选择 allPostsByAuthorAUTHORNAME 撰写的所有文章应显示在查询窗格右侧的结果窗格中。如下所示:

    { "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": "<token>" } } }
  9. 用上次查询返回的值更新 nextToken 参数,如下所示:

    query allPostsByAuthor { allPostsByAuthor( author: "AUTHORNAME" limit: 5 nextToken: "<token>" ) { posts { id title } nextToken } }
  10. 选择运行(橙色播放按钮),然后选择 allPostsByAuthorAUTHORNAME 撰写的其余文章应显示在查询窗格右侧的结果窗格中。如下所示:

    { "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 类型一直是平面键/值对象。您也可以使用解析器对复杂对象进行建模,例如集、列表和映射。让我们更新 Post 类型,加入标签。一篇文章可以具有 0 个或更多标签,这些标签作为字符串集存储在 DynamoDB 中。您还将设置一些变更,用于添加并删除标签;还要用一个新查询扫描具有特定标签的文章。

设置您的数据

  1. 在您的 API 中,选择架构选项卡。

  2. Schema (架构) 窗格中修改 Post 类型,添加新的 tags 字段,如下所示:

    type Post { id: ID! author: String title: String content: String url: String ups: Int! downs: Int! version: Int! tags: [String!] }
  3. Schema (架构) 窗格中修改 Query 类型,添加新的 allPostsByTag 查询,如下所示:

    type Query { allPostsByTag(tag: String!, limit: Int, nextToken: String): PaginatedPosts! allPostsByAuthor(author: String!, limit: Int, nextToken: String): PaginatedPosts! allPost(limit: Int, nextToken: String): PaginatedPosts! getPost(id: ID): Post }
  4. Schema (架构) 窗格中修改 Mutation 类型,添加新的 addTagremoveTag 变更,如下所示:

    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! }
  5. 选择 Save Schema (保存架构)

  6. 在右侧的解析器窗格中,找到 Query 类型上的新创建的 allPostsByTag 字段,然后选择附加。使用下面的代码片段创建您的解析器:

    import * as ddb from '@aws-appsync/utils/dynamodb'; export function request(ctx) { const { limit = 20, nextToken, tag } = ctx.arguments; return ddb.scan({ limit, nextToken, filter: { tags: { contains: tag } } }); } export function response(ctx) { const { items: posts = [], nextToken } = ctx.result; return { posts, nextToken }; }
  7. 保存对您的解析器所做的任何更改。

  8. 现在,使用下面的代码片段为 Mutation 字段 addTag 执行相同的操作:

    注意

    尽管 DynamoDB 实用程序当前不支持集操作,但您仍然可以自行构建请求以与集进行交互。

    import { util } from '@aws-appsync/utils' export function request(ctx) { const { id, tag } = ctx.arguments const expressionValues = util.dynamodb.toMapValues({ ':plusOne': 1 }) expressionValues[':tags'] = util.dynamodb.toStringSet([tag]) return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id }), update: { expression: `ADD tags :tags, version :plusOne`, expressionValues, }, } } export const response = (ctx) => ctx.result
  9. 保存对您的解析器所做的任何更改。

  10. 使用下面的代码片段为 Mutation 字段 removeTag 再重复一次该操作:

    import { util } from '@aws-appsync/utils'; export function request(ctx) { const { id, tag } = ctx.arguments; const expressionValues = util.dynamodb.toMapValues({ ':plusOne': 1 }); expressionValues[':tags'] = util.dynamodb.toStringSet([tag]); return { operation: 'UpdateItem', key: util.dynamodb.toMapValues({ id }), update: { expression: `DELETE tags :tags ADD version :plusOne`, expressionValues, }, }; } export const response = (ctx) => ctx.resultexport
  11. 保存对您的解析器所做的任何更改。

调用 API 以处理标签

您现已设置解析器,Amazon AppSync 知道如何将传入的 addTagremoveTagallPostsByTag 请求转换为 DynamoDB UpdateItemScan 操作。我们选择您之前创建的一个文章进行尝试。例如,我们使用作者为 Nadia 的一篇文章。

使用标签

  1. 在您的 API 中,选择查询选项卡。

  2. 查询窗格中,添加以下查询:

    query allPostsByAuthor { allPostsByAuthor( author: "Nadia" ) { posts { id title } nextToken } }
  3. 选择运行(橙色播放按钮),然后选择 allPostsByAuthor

  4. Nadia 的所有文章应显示在查询窗格右侧的结果窗格中。如下所示:

    { "data": { "allPostsByAuthor": { "posts": [ { "id": "10", "title": "The cutest dog in the world" }, { "id": "11", "title": "Did you known...?" } ], "nextToken": null } } }
  5. 让我们使用标题为 The cutest dog in the world 的文章。记下其 id,因为您稍后使用该 ID。现在,让我们尝试添加一个 dog 标签。

  6. 查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值。

    mutation addTag { addTag(id:10 tag: "dog") { id title tags } }
  7. 选择运行(橙色播放按钮),然后选择 addTag。将使用新标签更新该文章:

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
  8. 您可以添加更多标签。更新变更以将 tag 参数更改为 puppy

    mutation addTag { addTag(id:10 tag: "puppy") { id title tags } }
  9. 选择运行(橙色播放按钮),然后选择 addTag。将使用新标签更新该文章:

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } } }
  10. 您也可以删除标签。在查询窗格中,添加以下变更。您还需要将 id 参数更新为您以前记下的值:

    mutation removeTag { removeTag(id:10 tag: "puppy") { id title tags } }
  11. 选择运行(橙色播放按钮),然后选择 removeTag。文章已更新,puppy 标签已删除。

    { "data": { "addTag": { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog" ] } } }
  12. 您也可以搜索所有具有标签的文章。在查询窗格中,添加以下查询:

    query allPostsByTag { allPostsByTag(tag: "dog") { posts { id title tags } nextToken } }
  13. 选择运行(橙色播放按钮),然后选择 allPostsByTag。将返回具有 dog 标签的所有文章,如下所示:

    { "data": { "allPostsByTag": { "posts": [ { "id": "10", "title": "The cutest dog in the world", "tags": [ "dog", "puppy" ] } ], "nextToken": null } } }

结论

在本教程中,您构建了一个 API,可用于通过 Amazon AppSync 和 GraphQL 处理 DynamoDB 中的 Post 对象。

要进行清理,您可以从控制台中删除 Amazon AppSync GraphQL API。

要删除与您的 DynamoDB 表关联的角色,请在数据源表中选择您的数据源,然后单击编辑。记下创建或使用现有角色下面的角色值。转到 IAM 控制台以删除该角色。

要删除您的 DynamoDB 表,请在数据源列表中单击该表名称。这会转到 DynamoDB 控制台,您可以在其中删除该表。