

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

# 在中使用亚马逊 OpenSearch 服务解析器 AWS AppSync
<a name="tutorial-elasticsearch-resolvers"></a>

**注意**  
我们现在主要支持 APPSYNC\$1JS 运行时系统及其文档。请考虑使用 APPSYNC\$1JS 运行时系统和[此处](https://docs.aws.amazon.com/appsync/latest/devguide/tutorials-js.html)的指南。

AWS AppSync 支持从您在自己的 AWS 账户中配置的域中使用 Amazon OpenSearch 服务，前提是这些域不存在于 VPC 中。预置域后，您可以使用数据来源连接这些域，此时，您可以在架构中配置一个解析器以执行 GraphQL 操作（如查询、变更和订阅）。本教程将引导您了解一些常见示例。

有关更多信息，请参阅[解析器映射模板参考。 OpenSearch](resolver-mapping-template-reference-elasticsearch.md#aws-appsync-resolver-mapping-template-reference-elasticsearch)

## 一键设置
<a name="one-click-setup"></a>

要在配置了 AWS AppSync 亚马逊 OpenSearch 服务的情况下自动设置 GraphQL 终端节点，您可以使用以下 AWS CloudFormation 模板：

[https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/appsynces.yml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/appsynces.yml)

 AWS CloudFormation 部署完成后，您可以直接跳到[运行 GraphQL 查询和](#tutorial-elasticsearch-resolvers-perform-queries-mutations)突变。

## 创建新的 OpenSearch 服务域
<a name="create-a-new-es-domain"></a>

要开始使用本教程，您需要一个现有的 OpenSearch 服务域。如果您没有域，可以使用以下示例。请注意，创建 OpenSearch 服务域最多可能需要 15 分钟，然后才能继续将其与 AWS AppSync数据源集成。

```
aws cloudformation create-stack --stack-name AppSyncOpenSearch \
--template-url https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/ESResolverCFTemplate.yaml \
--parameters ParameterKey=OSDomainName,ParameterValue=ddtestdomain ParameterKey=Tier,ParameterValue=development \
--capabilities CAPABILITY_NAMED_IAM
```

您可以在自己的 AWS 账户中在美国西部 2（俄勒冈）地区启动以下 AWS CloudFormation 堆栈：

 [https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/ESResolverCFTemplate.yaml](https://console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks/new?templateURL=https://s3.us-west-2.amazonaws.com/awsappsync/resources/elasticsearch/ESResolverCFTemplate.yaml)

## 为 OpenSearch 服务配置数据源
<a name="configure-data-source-for-es"></a>

创建 OpenSearch 服务域后，导航到您的 AWS AppSync GraphQL API，然后选择 “**数据源**” 选项卡。选择**新建**，并为数据来源输入一个友好名称，例如“oss”。然后选择 **Amazon OpenSearch 域**作为**数据源类型**，选择相应的区域，您应该会看到您的 OpenSearch 服务域已列出。选择后，您可以创建一个新角色并 AWS AppSync 分配适合角色的权限，也可以选择具有以下内联策略的现有角色：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Sid": "Stmt1234234",
            "Effect": "Allow",
            "Action": [
                "es:ESHttpDelete",
                "es:ESHttpHead",
                "es:ESHttpGet",
                "es:ESHttpPost",
                "es:ESHttpPut"
            ],
            "Resource": [
                "arn:aws:es:us-east-1:111122223333:domain/democluster/*"
            ]
        }
    ]
}
```

------

您还需要 AWS AppSync 为该角色与建立信任关系：

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "appsync.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

------

此外， OpenSearch 服务域有自己的**访问策略**，您可以通过 Amazon Ser OpenSearch vice 控制台对其进行修改。您需要添加类似于以下内容的策略，其中包含适用于 OpenSearch 服务域的相应操作和资源。请注意，**委托**人将是 AppSync 数据源角色，如果您让控制台创建该角色，则可以在 IAM 控制台中找到该角色。

------
#### [ JSON ]

****  

```
{
    "Version":"2012-10-17",		 	 	 
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/service-role/APPSYNC_DATASOURCE_ROLE"
            },
            "Action": [
                "es:ESHttpDelete",
                "es:ESHttpHead",
                "es:ESHttpGet",
                "es:ESHttpPost",
                "es:ESHttpPut"
            ],
            "Resource": "arn:aws:es:us-east-1:111122223333:domain/DOMAIN_NAME/*"
        }
    ]
}
```

------

## 连接解析器
<a name="connecting-a-resolver"></a>

现在，数据源已连接到您的 OpenSearch 服务域，您可以使用解析器将其连接到您的 GraphQL 架构，如以下示例所示：

```
 schema {
   query: Query
   mutation: Mutation
 }

 type Query {
   getPost(id: ID!): Post
   allPosts: [Post]
 }

 type Mutation {
   addPost(id: ID!, author: String, title: String, url: String, ups: Int, downs: Int, content: String): AWSJSON
 }

type Post {
  id: ID!
  author: String
  title: String
  url: String
  ups: Int
  downs: Int
  content: String
}
...
```

请注意，有一个用户定义的 `Post` 类型（具有一个 `id` 字段）。在以下示例中，我们假设有一个过程（可以自动化）将此类型放入您的 OpenSearch 服务域，该过程将映射到的路径根目录`/post/_doc`，索引在`post`哪里。从该根路径中，您可以执行单独文档搜索、使用 `/id/post*` 的通配符搜索或使用 `/post/_search` 路径的多文档搜索。例如，如果您具有另一个名为 `User` 的类型，您可以使用名为 `user` 的新索引对文档编制索引，然后使用 `/user/_search` **路径**执行搜索。

在 AWS AppSync 控制台的架构编辑器中，修改前面的`Posts`架构以包含`searchPosts`查询：

```
type Query {
  getPost(id: ID!): Post
  allPosts: [Post]
  searchPosts: [Post]
}
```

保存架构。在右侧，对于 `searchPosts`，选择 **Attach resolver (附加解析器)**。在**操作**菜单中，选择**更新运行时**，然后选择**单位解析器 (仅限 VTL)**。然后，选择您的 OpenSearch 服务数据源。在**请求映射模板**部分，选择**查询文章**的下拉列表以获取基本模板。将 `path` 修改为 `/post/_search`。它应该类似以下内容：

```
{
    "version":"2017-02-28",
    "operation":"GET",
    "path":"/post/_search",
    "params":{
        "headers":{},
        "queryString":{},
        "body":{
            "from":0,
            "size":50
        }
    }
}
```

这假设前面的架构中包含已在 S OpenSearch ervice 中为该`post`字段编制索引的文档。如果您以不同方式设置数据的结构，将需要相应地进行更新。

在**响应映射模板**部分下，如果要从 OpenSearch 服务查询中取回数据结果并转换为 GraphQL，则需要指定相应的`_source`过滤器。使用以下模板：

```
[
    #foreach($entry in $context.result.hits.hits)
    #if( $velocityCount > 1 ) , #end
    $utils.toJson($entry.get("_source"))
    #end
]
```

## 修改您的搜索
<a name="modifying-your-searches"></a>

上述的请求映射模板针对所有记录执行一个简单查询。假设您想要按某个特定作者进行搜索。此外，假设您希望该作者是在 GraphQL 查询中定义的一个参数。在 AWS AppSync 控制台的架构编辑器中，添加一个 `allPostsByAuthor` 查询：

```
type Query {
  getPost(id: ID!): Post
  allPosts: [Post]
  allPostsByAuthor(author: String!): [Post]
  searchPosts: [Post]
}
```

现在选择 Att **ach resolver** 并选择 OpenSearch 服务数据源，但在**响应映射模板**中使用以下示例：

```
{
    "version":"2017-02-28",
    "operation":"GET",
    "path":"/post/_search",
    "params":{
        "headers":{},
        "queryString":{},
        "body":{
            "from":0,
            "size":50,
            "query":{
                "match" :{
                    "author": $util.toJson($context.arguments.author)
                }
            }
        }
    }
}
```

请注意，`body` 用一个针对 `author` 字段的术语查询填充，它将作为一个参数从客户端进行传递。您可以选择已预填充信息（如标准文本），甚至使用其他[实用程序](resolver-context-reference.md#aws-appsync-resolver-mapping-template-context-reference)。

如果您使用此解析器，则使用上例所示的相同信息填写**响应映射模板**。

## 向 OpenSearch 服务添加数据
<a name="adding-data-to-es"></a>

由于 GraphQL 突变，您可能需要向 OpenSearch 服务域中添加数据。这是一个用于搜索和其他用途的强大机制。由于您可以使用 GraphQL 订阅来[实现实时数据](aws-appsync-real-time-data.md)，因此它可以用作通知客户服务域中数据 OpenSearch 更新的机制。

返回 AWS AppSync 控制台的 “**架构**” 页面，为`addPost()`突变选择**附加解析器**。再次选择 OpenSearch 服务数据源，然后为`Posts`架构使用以下**响应映射模板**：

```
{
    "version":"2017-02-28",
    "operation":"PUT",
    "path": $util.toJson("/post/_doc/$context.arguments.id"),
    "params":{
        "headers":{},
        "queryString":{},
        "body":{
            "id": $util.toJson($context.arguments.id),
            "author": $util.toJson($context.arguments.author),
            "ups": $util.toJson($context.arguments.ups),
            "downs": $util.toJson($context.arguments.downs),
            "url": $util.toJson($context.arguments.url),
            "content": $util.toJson($context.arguments.content),
            "title": $util.toJson($context.arguments.title)
        }
    }
}
```

和之前一样，这是一个介绍如何设置数据的结构的示例。如果您有不同的字段名称或索引，则需要相应地更新 `path` 和 `body`。此示例还显示如何使用 `$context.arguments` 从您的 GraphQL 变更参数填充模板。

在继续之前，使用以下响应映射模板，这会返回变更操作结果或错误信息以作为输出：

```
#if($context.error)
    $util.toJson($ctx.error)
#else
    $util.toJson($context.result)
#end
```

## 检索单个文档
<a name="retrieving-a-single-document"></a>

最后，如果您想在您的架构中使用 `getPost(id:ID)` 查询以返回单个文档，请在 AWS AppSync 控制台的架构编辑器中找到此查询，然后选择 **Attach resolver (附加解析程序)**。再次选择 OpenSearch 服务数据源并使用以下映射模板：

```
{
    "version":"2017-02-28",
    "operation":"GET",
    "path": $util.toJson("post/_doc/$context.arguments.id"),
    "params":{
        "headers":{},
        "queryString":{},
        "body":{}
    }
}
```

由于上面的 `path` 将 `id` 参数用于空正文，此命令将返回单个文档。但是，您需要使用以下响应映射模板，因为现在您返回的是单个项目而不是列表：

```
$utils.toJson($context.result.get("_source"))
```

## 执行查询和变更
<a name="tutorial-elasticsearch-resolvers-perform-queries-mutations"></a>

现在，您应该能够对您的 OpenSearch 服务域执行 GraphQL 操作了。导航到 AWS AppSync 控制台的 “**查询**” 选项卡并添加一条新记录：

```
mutation addPost {
    addPost (
        id:"12345"
        author: "Fred"
        title: "My first book"
        content: "This will be fun to write!"
        url: "publisher website",
        ups: 100,
        downs:20 
       )
}
```

您将会在右侧看到变更结果。同样，您现在可以对您的 OpenSearch 服务域运行`searchPosts`查询：

```
query searchPosts {
    searchPosts {
        id
        title
        author
        content
    }
}
```

## 最佳实践
<a name="best-practices"></a>
+ OpenSearch 服务应该用于查询数据，而不是作为您的主数据库。如组合 GraphQL 解 OpenSearch 析器中所述，您可能需要将服务与亚马逊 DynamoDB [结合](tutorial-combining-graphql-resolvers.md#aws-appsync-tutorial-combining-graphql-resolvers)使用。
+ 仅通过允许 AWS AppSync 服务角色访问集群来授予对域的访问权限。
+ 您可以通过最低成本的集群先开始小规模开发，然后随着您转向生产阶段，而转至具有高可用性 (HA) 的较大集群。