

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

# 使用 DynamoDB JavaScript 解析器创建简单的后期应用程序
<a name="tutorial-dynamodb-resolvers-js"></a>

在本教程中，您将导入您的 Amazon DynamoDB 表并将其连接起来， AWS AppSync 以便 JavaScript 使用可以在自己的应用程序中使用的管道解析器构建功能齐全的 GraphQL API。

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

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

## 创建您的 GraphQL API
<a name="create-graphql-api"></a>

**要在中创建 GraphQL API AWS AppSync**

1. 打开 AppSync 控制台并选择**创建 API**。

1. 选择**从头开始设计**，然后选择**下一步**。

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

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

## 定义基本文章 API
<a name="define-post-api"></a>

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

**将数据添加到您的架构**

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

1. 我们将创建一个架构，它定义 `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!
   }
   ```

1. 选择 **Save Schema (保存架构)**。

## 设置您的 Amazon DynamoDB 表
<a name="configure-dynamodb"></a>

 AWS AppSync 控制台可以帮助预配置将您自己的 AWS 资源存储在 Amazon DynamoDB 表中所需的资源。在该步骤中，您创建一个 Amazon DynamoDB 表以存储您的文章。您还会设置我们稍后使用的[二级索引](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/SecondaryIndexes.html)。

**创建您的 Amazon DynamoDB 表**

1. 在**架构**页面上，选择**创建资源**。

1. 选择**使用现有的类型**，然后选择 `Post` 类型。

1. 在**其他索引**部分中，选择**添加索引**。

1. 将索引命名为 `author-index`。

1. 将 `Primary key` 设置为 `author`，并将 `Sort` 键设置为 `None`。

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

1. 选择**创建**。

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

## 设置 AddPost 解析器 (亚马逊 DynamoDB) PutItem
<a name="configure-addpost"></a>

现在已经知道 AWS AppSync 了 Amazon DynamoDB 表，您可以通过定义解析器将其链接到各个查询和变更。您创建的第一个解析器是使用的`addPost`管道解析器 JavaScript，它允许您在 Amazon DynamoDB 表中创建帖子。管道解析器具有以下组件：
+ GraphQL 架构中的位置，用于附加解析器。在本例中，您将设置 `createPost` 类型的 `Mutation` 字段的解析器。在调用方调用 `{ addPost(...){...} }` 变更时，将调用该解析器。
+ 此解析器所用的数据来源。在该示例中，您希望使用以前定义的 DynamoDB 数据来源，因此，您可以在 `post-table-for-tutorial` DynamoDB 表中添加条目。
+ 请求处理程序。请求处理程序是一个函数，用于处理来自调用者的传入请求，并将其转换为 AWS AppSync 要对 DynamoDB 执行的指令。
+ 响应处理程序。响应处理程序的任务是，处理来自 DynamoDB 的响应，并将其转换回 GraphQL 所需的内容。如果 DynamoDB 中的数据形态与 GraphQL 中的 `Post` 类型不同，此模板很有用。但在此例中它们的形态相同，所以只用于传递数据。

**设置您的解析器**

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

1. 在**解析器**窗格中，找到 `Mutation` 类型下面的 `addPost` 字段，然后选择**附加**。

1. 选择您的数据来源，然后选择**创建**。

1. 在代码编辑器中，将代码替换为以下代码片段：

   ```
   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
   }
   ```

1. 选择**保存**。

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

AWS AppSync 附带一个名为的自动生成ID的实用程序`util.autoId()`，用于为您的新帖子生成ID。如果您未指定 ID，该实用程序将自动为您生成 ID。

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

有关可用实用程序的更多信息 JavaScript，请参阅[解析器和函数的JavaScript运行时功能](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference-js.html)。

### 调用 API 以添加文章
<a name="call-api-addpost"></a>

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

**运行操作**

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

1. 在**查询**窗格中，添加以下变更：

   ```
   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
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `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. AWS AppSync 收到了`addPost`变异请求。

1. AWS 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/' }
     }
   }
   ```

1. AWS AppSync 使用此值生成和执行 Amazon DynamoDB 请求`PutItem`。

1. AWS 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
   }
   ```

1. 响应处理程序立即返回结果 (`return ctx.result`)。

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

## 设置 GetPost 解析器（亚马逊 DynamoDB） GetItem
<a name="configure-getpost"></a>

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

**添加您的解析器**

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

1. 在右侧的**解析器**窗格中，找到 `Query` 类型上的 `getPost` 字段，然后选择**附加**。

1. 选择您的数据来源，然后选择**创建**。

1. 在代码编辑器中，将代码替换为以下代码片段：

   ```
   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
   ```

1. 保存解析器。

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

### 调用 API 以获取文章
<a name="call-api-getpost"></a>

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

**运行您的查询**

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

1. 在**查询**窗格中，添加以下代码，并使用您在创建文章后复制的 ID：

   ```
   query getPost {
     getPost(id: "123") {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `getPost`。新创建的文章的结果应显示在**查询**窗格右侧的**结果**窗格中。

1. 从 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` 查询仅需要 `id`、`author` 和 `title`，您可以将请求函数更改为使用投影表达式仅指定您希望从 DynamoDB 表中获取的属性，以避免将不必要的数据从 DynamoDB 传输到 AWS 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
```

您也可以使用w [selectionSetList](https://docs.aws.amazon.com/appsync/latest/devguide/resolver-context-reference-js.html#aws-appsync-resolver-context-reference-info-js)it `getPost` h来表示`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 突变 (亚马逊 DynamoDB) UpdateItem
<a name="configure-updatepost"></a>

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

**更新您的解析器**

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

1. 在 **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!
   }
   ```

1. 选择 **Save Schema (保存架构)**。

1. 在右侧的**解析器**窗格中，找到 `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;
   ```

1. 保存您所做的任何更改。

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

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

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

有关条件表达式的更多信息，请参阅[条件表达式](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-condition-expressions)文档。

有关该`UpdateItem`请求的更多信息，请参阅[UpdateItem](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-updateitem)文档和 [DynamoDB 模块](https://docs.aws.amazon.com/appsync/latest/devguide/built-in-modules-js.html)文档。

有关如何编写更新表达式的更多信息，请参阅 [DynamoDB 文档 UpdateExpressions](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Expressions.UpdateExpressions.html)。

### 调用 API 以更新文章
<a name="call-api-updatepost"></a>

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

**更新您的对象**

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

1. 在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值：

   ```
   mutation updatePost {
     updatePost(
       id:123
       title: "An empty story"
       content: null
       expectedVersion: 1
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `updatePost`。

1. 在 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
       }
     }
   }
   ```

在此请求中，您要求 AWS AppSync 和亚马逊 DynamoDB 仅更新和字段`title`。`content`所有其他字段保持不变（除了递增 `version` 字段以外）。您将 `title` 属性设置为新的值，并从文章中删除 `content` 属性。`author`、`url`、`ups` 和 `downs` 字段没有变化。再次尝试执行变更请求，同时将请求完全保持原样。您可以看到类似以下内容的响应：

```
{
  "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`。

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

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

## 创建投票突变 (亚马逊 DynamoDB) UpdateItem
<a name="configure-vote-mutations"></a>

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

**添加您的变更**

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

1. 在**架构**窗格中，修改 `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
   }
   ```

1. 选择 **Save Schema (保存架构)**。

1. 在右侧的**解析器**窗格中，找到 `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;
   ```

1. 保存您所做的任何更改。

### 调用 API 以对文章点赞或差评
<a name="call-api-vote"></a>

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

**运行您的变更**

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

1. 在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值：

   ```
   mutation votePost {
     vote(id:123, direction: UP) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `votePost`。

1. 在 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
       }
     }
   }
   ```

1. 再选择几次**运行**。每次执行查询时，您应该会看到 `ups` 和 `version` 字段增加 `1`。

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

   ```
   mutation votePost {
     vote(id:123, direction: DOWN) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `votePost`。

   这次，每次运行查询时，您应该会看到 `downs` 和 `version` 字段增加 `1`。

## 设置 DeletePost 解析器（亚马逊 DynamoDB） DeleteItem
<a name="configure-deletepost"></a>

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

**添加您的变更**

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

1. 在**架构**窗格中，修改 `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!
   }
   ```

1. 这次，您将 `expectedVersion` 字段设置为可选。接下来，选择**保存架构**。

1. 在右侧的**解析器**窗格中，找到 `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](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-deleteitem)文档。

### 调用 API 以删除文章
<a name="call-api-delete"></a>

现在解析器已经设置好了，我 AWS AppSync 知道如何将传入的`delete`突变转换为 Amazon DynamoDB 操作。`DeleteItem`现在，您可以运行变更，从表中删除一些内容。

**运行您的变更**

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

1. 在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值：

   ```
   mutation deletePost {
     deletePost(id:123) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `deletePost`。

1. 将从 Amazon DynamoDB 中删除该文章。****请注意， AWS 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
       }
     }
   }
   ```

1. 只有在对 `deletePost` 的该调用实际将其从 Amazon DynamoDB 中删除时，才会返回该值。再次选择**运行**。

1. 调用仍然成功，但没有返回任何值：

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

1. 现在，让我们尝试删除一篇文章，但这次指定 `expectedValue`。首先，您需要创建一个新文章，因为您刚刚删除了迄今为止一直使用的文章。

1. 在**查询**窗格中，添加以下变更：

   ```
   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
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `addPost`。

1. 新创建的文章的结果应显示在**查询**窗格右侧的**结果**窗格中。记下新创建的对象的 `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
       }
     }
   }
   ```

1. 现在，让我们尝试删除具有非法 **expectedVersion** 值的文章。在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值：

   ```
   mutation deletePost {
     deletePost(
       id:123
       expectedVersion: 9999
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `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)"
       }
     ]
   }
   ```

1. 请求失败，因为条件表达式的评估结果为 `false`。Amazon DynamoDB 中的文章 `version` 值与参数中指定的 `expectedValue` 不匹配。对象的当前值返回到 GraphQL 响应的 `data` 部分的 `errors` 字段中。重试请求，但更正 `expectedVersion`：

   ```
   mutation deletePost {
     deletePost(
       id:123
       expectedVersion: 1
     ) {
       id
       author
       title
       content
       url
       ups
       downs
       version
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `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
       }
     }
   }
   ```

1. 再次选择**运行**。调用仍然成功，但这次没有返回任何值，因为已在 Amazon DynamoDB 中删除该文章。

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

## 设置 allPost 解析器 (Amazon DynamoDB Scan)
<a name="configure-allpost"></a>

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

**添加您的变更**

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

1. 在 **Schema (架构)** 窗格中修改 `Query` 类型，添加新的 `allPost` 查询，如下所示：

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

1. 添加新 `PaginationPosts` 类型：

   ```
   type PaginatedPosts {
       posts: [Post!]!
       nextToken: String
   }
   ```

1. 选择 **Save Schema (保存架构)**。

1. 在右侧的**解析器**窗格中，找到 `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` 值来自何处）。

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

有关 `Scan` 请求的更多信息，请参阅 [Scan](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-scan) 参考文档。

### 调用 API 以扫描所有文章
<a name="call-api-scan"></a>

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

**添加和查询数据**

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

1. 在**查询**窗格中，添加以下变更：

   ```
   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 }
   }
   ```

1. 选择**运行**（橙色播放按钮）。

1. 现在，让我们扫描表，每次返回 5 个结果。在**查询**窗格中，添加以下查询：

   ```
   query allPost {
     allPost(limit: 5) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `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>"
       }
     }
   }
   ```

1. 您收到 5 个结果和一个 `nextToken`（可用于获取下一组结果）。更新 `allPost` 查询，加入上一组结果的 `nextToken`：

   ```
   query allPost {
     allPost(
       limit: 5
       nextToken: "<token>"
     ) {
       posts {
         id
         author
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `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
       }
     }
   }
   ```

## 设置 allPostsBy作者解析器（亚马逊 DynamoDB 查询）
<a name="configure-query"></a>

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

**添加您的查询**

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

1. 在 **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` 类型。

1. 选择 **Save Schema (保存架构)**。

1. 在右侧的**解析器**窗格中，找到 `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` 值）。

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

有关 `Query` 请求的更多信息，请参阅 [Query](https://docs.aws.amazon.com/appsync/latest/devguide/js-resolver-reference-dynamodb.html#js-aws-appsync-resolver-reference-dynamodb-query) 参考文档。

### 调用 API 以查询作者的所有文章
<a name="call-api-query"></a>

现在解析器已经设置好了，我 AWS AppSync 知道如何将传入的`allPostsByAuthor`突变转换为针对索引的 DynamoDB 操作`Query`。`author-index`现在，您可以查询表，检索某一作者的所有文章。

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

**添加数据和查询**

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

1. 在**查询**窗格中，添加以下变更：

   ```
   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 }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `addPost`。

1. 现在，让我们查询表，返回作者为 `Nadia` 的所有文章。在**查询**窗格中，添加以下查询：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(author: "Nadia") {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `allPostsByAuthor`。`Nadia` 撰写的所有文章应显示在**查询**窗格右侧的**结果**窗格中。如下所示：

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "10",
             "title": "The cutest dog in the world"
           },
           {
             "id": "11",
             "title": "Did you know...?"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

1. `Query` 的分页方式与 `Scan` 相同。例如，如果我们查找作者为 `AUTHORNAME` 的所有文章，每次显示 5 个结果。

1. 在**查询**窗格中，添加以下查询：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "AUTHORNAME"
       limit: 5
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `allPostsByAuthor`。`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": "<token>"
       }
     }
   }
   ```

1. 用上次查询返回的值更新 `nextToken` 参数，如下所示：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "AUTHORNAME"
       limit: 5
       nextToken: "<token>"
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `allPostsByAuthor`。`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
       }
     }
   }
   ```

## 使用集
<a name="using-sets"></a>

到目前为止，该`Post`类型一直是一个平面 key/value 对象。您也可以使用解析器对复杂对象进行建模，例如集、列表和映射。让我们更新 `Post` 类型，加入标签。一篇文章可以具有 0 个或更多标签，这些标签作为字符串集存储在 DynamoDB 中。您还将设置一些变更，用于添加并删除标签；还要用一个新查询扫描具有特定标签的文章。

**设置您的数据**

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

1. 在 **Schema (架构)** 窗格中修改 `Post` 类型，添加新的 `tags` 字段，如下所示：

   ```
   type Post {
     id: ID!
     author: String
     title: String
     content: String
     url: String
     ups: Int!
     downs: Int!
     version: Int!
     tags: [String!]
   }
   ```

1. 在 **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
   }
   ```

1. 在 **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!
   }
   ```

1. 选择 **Save Schema (保存架构)**。

1. 在右侧的**解析器**窗格中，找到 `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 };
   }
   ```

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

1. 现在，使用下面的代码片段为 `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
   ```

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

1. 使用下面的代码片段为 `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
   ```

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

### 调用 API 以处理标签
<a name="call-api-tags"></a>

现在您已经设置了解析器， AWS AppSync 知道如何将传入的`addTag``removeTag`、和`allPostsByTag`请求转换为 D `UpdateItem` ynamo `Scan` DB 和操作。我们选择您之前创建的一个文章进行尝试。例如，我们使用作者为 `Nadia` 的一篇文章。

**使用标签**

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

1. 在**查询**窗格中，添加以下查询：

   ```
   query allPostsByAuthor {
     allPostsByAuthor(
       author: "Nadia"
     ) {
       posts {
         id
         title
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `allPostsByAuthor`。

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

   ```
   {
     "data": {
       "allPostsByAuthor": {
         "posts": [
           {
             "id": "10",
             "title": "The cutest dog in the world"
           },
           {
             "id": "11",
             "title": "Did you known...?"
           }
         ],
         "nextToken": null
       }
     }
   }
   ```

1. 让我们使用标题为 *The cutest dog in the world* 的文章。记下其 `id`，因为您稍后使用该 ID。现在，让我们尝试添加一个 `dog` 标签。

1. 在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值。

   ```
   mutation addTag {
     addTag(id:10 tag: "dog") {
       id
       title
       tags
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `addTag`。将使用新标签更新该文章：

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog"
         ]
       }
     }
   }
   ```

1. 您可以添加更多标签。更新变更以将 `tag` 参数更改为 `puppy`：

   ```
   mutation addTag {
     addTag(id:10 tag: "puppy") {
       id
       title
       tags
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `addTag`。将使用新标签更新该文章：

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog",
           "puppy"
         ]
       }
     }
   }
   ```

1. 您也可以删除标签。在**查询**窗格中，添加以下变更。您还需要将 `id` 参数更新为您以前记下的值：

   ```
   mutation removeTag {
     removeTag(id:10 tag: "puppy") {
       id
       title
       tags
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `removeTag`。文章已更新，`puppy` 标签已删除。

   ```
   {
     "data": {
       "addTag": {
         "id": "10",
         "title": "The cutest dog in the world",
         "tags": [
           "dog"
         ]
       }
     }
   }
   ```

1. 您也可以搜索所有具有标签的文章。在**查询**窗格中，添加以下查询：

   ```
   query allPostsByTag {
     allPostsByTag(tag: "dog") {
       posts {
         id
         title
         tags
       }
       nextToken
     }
   }
   ```

1. 选择**运行**（橙色播放按钮），然后选择 `allPostsByTag`。将返回具有 `dog` 标签的所有文章，如下所示：

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

## 结论
<a name="conclusion-dynamodb-tutorial-js"></a>

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

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

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

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