教程:Amazon Elasticsearch Service 解析程序 - AWS AppSync
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

教程:Amazon Elasticsearch Service 解析程序

AWS AppSync 支持从您已经在自己的 AWS 账户中预配置的域(假定它们不在 VPC 中)中使用 Amazon Elasticsearch Service。预配置域后,您可以使用数据源连接这些域,此时,您可以在架构中配置一个解析程序以执行 GraphQL 操作(如查询、更改和订阅)。本教程将引导您了解一些常见示例。

有关更多信息,请参阅 Elasticsearch 解析程序映射模板参考

一键设置

如果您希望在 AWS AppSync(配置了 Amazon Elasticsearch Service)中自动设置一个 GraphQL 终端节点,您可以使用以下 AWS CloudFormation 模板:

AWS CloudFormation 部署完成后,可以直接跳到运行 GraphQL 查询和更改

创建新的 Amazon ES 域

要开始使用本教程,您需要一个现有的 Amazon ES 域。如果您没有域,可以使用以下示例。请注意,创建 Amazon ES 域可能需要多达 15 分钟时间,然后才能继续操作以将此域与 AWS AppSync 数据源集成。

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

您可以在您的 AWS 账户中启动位于美国西部 2(俄勒冈)区域的此 AWS CloudFormation 堆栈:

为 Amazon ES 配置数据源

创建 Amazon ES 域后,导航至 AWS AppSync GraphQL API,然后选择 Data Sources (数据源) 选项卡。选择 New (新建) 并为数据源输入友好名称,例如“Elasticsearch”。然后,对于 Data source type (数据源类型) 选择 Amazon Elasticsearch domain (Amazon Elasticsearch 域),选择适当的区域,此时您应看到已列出您的 Amazon ES 域。选择此域后,您可以创建新的角色,AWS AppSync 将分配与角色相应的权限;您也可以选择现有角色,该角色具有以下内联策略:

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

您还需要为该角色设置与 AWS AppSync 的信任关系:

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

此外,Amazon ES 域具有它自己的访问策略,您可以通过 Amazon Elasticsearch Service 控制台修改此策略。您将需要使用适合于 Amazon ES 域的操作和资源,添加与下面内容类似的策略。请注意,委托人将成为 AppSync 数据源角色,如果您使用控制台创建此角色,此角色将以 appsync-datasource-es- 的名称开头且可以在 AWS IAM 控制台中找到。

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

连接解析程序

既然数据源连接到您的 Amazon ES 域,您就可以通过解析程序将其连接到您的架构,如以下示例所示:

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): Post } type Post { id: ID! author: String title: String url: String ups: Int downs: Int content: String } ...

请注意,有一个用户定义的 Post 类型(具有一个 id 字段)。在下面的示例中,我们假定有一个进程(可自动执行)用于将此类型放入到 Amazon ES 域中,此域映射到 /id/post 的路径根目录,其中 id 是索引,而 post 是类型。在此根路径中,您可以通过 /id/post* 执行单独的文档搜索、通配符搜索;或者通过路径 /id/post/_search 执行多文档搜索。如果您有另一个类型 User(例如,在同一个索引 id 下编入索引的类型),您可以通过路径 /id/_search 执行多文档搜索。这会同时搜索 PostUser 上的字段。

从 AWS AppSync 控制台中的架构编辑器内,修改前面的 Posts 架构以包含 searchPosts 查询:

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

保存架构。在右侧,对于 searchPosts,选择 Attach resolver (附加解析程序)。选择您的 Amazon ES 数据源。在 request mapping template (请求映射模板) 部分下,选择 Query posts (查询文章) 的下拉列表以获取基本模板。将 path 修改为 /id/post/_search。它应该类似以下内容:

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

这假设上述架构具有带 id 字段的文档,并且文档已在 Amazon ES 按此字段编入索引。如果您以不同方式设置数据的结构,将需要相应地进行更新。

response mapping template (响应映射模板) 部分,如果您希望从 Amazon ES 查询取回数据结果并将结果转换为 GraphQL,您需要指定适当的 _source 筛选条件。使用以下模板:

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

修改您的搜索

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

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

现在,选择 Attach resolver (附加解析程序) 并选择 Amazon ES 数据源,但在响应映射模板中使用以下示例:

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

请注意,body 用一个针对 author 字段的术语查询填充,它将作为一个参数从客户端进行传递。您可以选择已预填充信息(如标准文本),甚至使用其他实用程序

如果您使用此解析程序,则使用上例所示的相同信息填写响应映射模板

将数据添加到 Amazon ES

您可能希望将数据作为 GraphQL 更改的结果添加到 Amazon ES 域。这是一个用于搜索和其他用途的强大机制。由于您可以使用 GraphQL 订阅以使您的数据变为实时的,因此它用作一种通知机制,用于将对您的 Amazon ES 域中数据进行的更新告知客户端。

返回到 AWS AppSync 控制台中的 Schema (架构) 页面,并为 addPost() 更改选择 Attach resolver (附加解析程序)。再次选择 Amazon ES 数据源,并将以下响应映射模板用于 Posts 架构:

{ "version":"2017-02-28", "operation":"PUT", "path": $util.toJson("/id/post/$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) } } }

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

在继续操作之前,使用以下响应映射模板,这将在下一部分中详细说明:

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

检索单个文档

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

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

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

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

执行查询和更改

您现在应该能够针对您的 Amazon ES 域执行 GraphQL 操作。导航到 AWS AppSync 控制台的 Queries (查询) 选项卡并添加新记录:

mutation { addPost( id:"12345" author: "Fred" title: "My first book" content: "This will be fun to write!" ){ id author title } }

如果此记录成功插入,您将在右侧看到相应字段。同样,您现在可以针对您的 Amazon ES 域运行 searchPosts 查询:

query { searchPosts { id title author content } }

最佳实践

  • Amazon ES 应该用于查询数据,而不是作为您的主数据库。您可能希望按照结合使用 GraphQL 解析程序中所述将 Amazon ES 与 Amazon DynamoDB 结合使用。

  • 通过允许 AWS AppSync 服务角色访问集群,仅授予针对您的域的访问权限。

  • 您可以通过最低成本的集群先开始小规模开发,然后随着您转向生产阶段,而转至具有高可用性 (HA) 的较大集群。