使用 Amazon Elasticsearch Service 创建搜索应用程序 - Amazon Elasticsearch Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 Amazon Web Services 服务入门

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

使用 Amazon Elasticsearch Service 创建搜索应用程序

使用 Amazon Elasticsearch Service (Amazon ES) 创建搜索应用程序的一个常用方法是使用 Web 表单将用户查询发送到服务器。然后,您可以授权服务器直接调用 Elasticsearch API 并让服务器向 Amazon ES 发送请求。

但是,如果您想编写不依赖服务器的客户端代码,则应针对安全和性能风险作出补偿。不建议允许对 Elasticsearch API 的未签名公有访问权限。用户可能会访问不安全的终端节点,或者通过过于广泛的查询(或过多的查询)影响集群性能。

本章为您提供了一个解决方案:使用 Amazon API Gateway 将用户限制到一部分 Elasticsearch API,并使用Amazon Lambda签署从 API Gateway 到亚马逊 ES 的请求。

注意

标准 API Gateway 和 Lambda 定价适用,但不能超出本教程的限制使用量,成本应忽略不计。

第 1 步:索引示例数据

这些步骤的一个先决条件是 Amazon ES 域。下载 sample-movies.zip,解压它,然后使用 _bulk API 将 5,000 个文档添加到 movies 索引:

POST https://search-my-domain.us-west-1.es.amazonaws.com/_bulk { "index": { "_index": "movies", "_type": "movie", "_id": "tt1979320" } } {"fields":{"directors":["Ron Howard"],"release_date":"2013-09-02T00:00:00Z","rating":8.3,"genres":["Action","Biography","Drama","Sport"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTQyMDE0MTY0OV5BMl5BanBnXkFtZTcwMjI2OTI0OQ@@._V1_SX400_.jpg","plot":"A re-creation of the merciless 1970s rivalry between Formula One rivals James Hunt and Niki Lauda.","title":"Rush","rank":2,"running_time_secs":7380,"actors":["Daniel Brühl","Chris Hemsworth","Olivia Wilde"],"year":2013},"id":"tt1979320","type":"add"} { "index": { "_index": "movies", "_type": "movie", "_id": "tt1951264" } } {"fields":{"directors":["Francis Lawrence"],"release_date":"2013-11-11T00:00:00Z","genres":["Action","Adventure","Sci-Fi","Thriller"],"image_url":"http://ia.media-imdb.com/images/M/MV5BMTAyMjQ3OTAxMzNeQTJeQWpwZ15BbWU4MDU0NzA1MzAx._V1_SX400_.jpg","plot":"Katniss Everdeen and Peeta Mellark become targets of the Capitol after their victory in the 74th Hunger Games sparks a rebellion in the Districts of Panem.","title":"The Hunger Games: Catching Fire","rank":4,"running_time_secs":8760,"actors":["Jennifer Lawrence","Josh Hutcherson","Liam Hemsworth"],"year":2013},"id":"tt1951264","type":"add"} ...

要了解更多信息,请参阅“在 Amazon Elasticsearch Service 中为数据建立索引”。

第 2 步:在 API Gateway 中创建 API

使用 API Gateway,您可以创建更加受限的 API 并简化与 Elasticsearch 交互的过程_searchAPI。API Gateway 让您可以启用 Amazon Cognito 身份验证和请求限制等安全功能。执行以下步骤来创建和部署 API:

创建和配置 API

使用 API Gateway 控制台创建 API

  1. 在 API Gateway 中,选择创建 API

  2. 定位REST API(非私有),然后选择构建

  3. 配置以下字段:

    • API 名称:search-es-api

    • 描述:用于搜索 Amazon Elasticsearch Service 域的公共 API

    • 终端节点类型:区域性的

  4. 选择 Create API (创建 API)

  5. 选择操作 >创建方法

  6. 选择GET,然后单击复选标记进行确认。

  7. 配置以下设置,然后单击Save

设置
集成类型 Lambda 函数
使用 Lambda 代理集成
Lambda 地区 us-west-1
Lambda 函数 search-es-lambda(稍后您将在 Lambda 中配置它)
使用默认超时

配置该方法请求

选择方法请求并配置以下设置:

设置
授权 NONE
请求验证器

验证查询字符串参数和标头

必需的 API 密钥 false

URL 查询字符串参数

设置
名称 q
必需

部署 API 并配置阶段

借助 API Gateway 控制台,您可以创建部署并将其与新的或现有阶段相关联,从而部署 API。

  1. 选择操作 >部署 API

  2. 适用于部署阶段选择新阶段并将舞台命名为search-es-api-test

  3. 选择 Deploy (部署)

  4. 在阶段编辑器中配置以下设置,然后选择保存更改

设置
启用限制
Rate

1000

突增 500

这些设置将配置一个 API,该 API 只有一个方法:一个针对终端节点根的 GET 请求 (https://some-id.execute-api.us-west-1.amazonaws.com/search-es-api-test)。该请求需要单个参数 (q) - 查询字符串要搜索的。调用后,该方法会将请求传递到 Lambda,Lambda 将运行search-es-lambdafunction. 有关更多信息,请参阅 。在 Amazon API Gateway 中创建 API在 Amazon API Gateway 中部署 API

第 3 步:创建并部署 Lambda 函数

在 API Gateway 中创建 API 后,创建它将请求传递到的 Lambda 函数。

创建 Lambda 函数

在此解决方案中,API Gateway 会将请求传递到以下 Python 3.8 Lambda 函数,该函数将查询 Amazon ES 并返回结果。将函数命名为search-es-lambda

由于此示例函数使用的是外部库,您需要创建一个部署程序包并将其上传到 Lambda,才能使代码正常运行。有关创建 Lambda 函数和部署程序包的更多信息,请参阅创建部署程序包 (Python)中的Amazon Lambda开发人员指南创建 Lambda 部署程序包

import boto3 import json import requests from requests_aws4auth import AWS4Auth region = '' # For example, us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) host = '' # The ES domain endpoint with https:// and a trailing slash index = 'movies' url = host + '/' + index + '/_search' # Lambda execution starts here def lambda_handler(event, context): # Put the user query into the query DSL for more accurate search results. # Note that certain fields are boosted (^). query = { "size": 25, "query": { "multi_match": { "query": event['queryStringParameters']['q'], "fields": ["fields.title^4", "fields.plot^2", "fields.actors", "fields.directors"] } } } # ES 6.x requires an explicit Content-Type header headers = { "Content-Type": "application/json" } # Make the signed HTTP request r = requests.get(url, auth=awsauth, headers=headers, data=json.dumps(query)) # Create the response and add some extra content to support CORS response = { "statusCode": 200, "headers": { "Access-Control-Allow-Origin": '*' }, "isBase64Encoded": False } # Add the search results to the response response['body'] = r.text return response

修改处理程序

这些区域有:handler是函数代码中处理事件的方法。您需要根据 Lambda 函数所在的部署包中的文件名更改处理程序名称。例如,如果您的文件名为es-function.py,请将处理程序重命名为es-function.lambda_handler。有关更多信息,请参阅 。Python 中的 Lambda 函数处理程序

配置触发器

选择添加触发器并创建调用函数的 HTTP 终端节点。触发器必须具有以下配置:

触发器 API 部署阶段 安全性
API Gateway search-es-api search-es-api-test 打开

第 4 步:修改域访问策略

您的亚马逊 ES 域必须允许 Lambda 函数使GET请求movies索引。以下策略提供search-es-lambda-role(通过 Lambda 创建)访问movies索引:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/service-role/search-es-lambda-role-1abcdefg" }, "Action": "es:ESHttpGet", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/movies/_search" } ] }
注意

要获取 Lambda 自动创建的角色的确切名称,请转到Amazon Identity and Access Management(IAM) 控制台,请选择角色,并搜索 “lambda”。

有关访问策略的更多信息,请参阅配置访问策略

第 5 步:测试 Web 应用程序

测试 Web 应用程序

  1. 下载 sample-site.zip,解压后在常用文本编辑器中打开 scripts/search.js

  2. 更新apigatewayendpoint变量来指向您的 API Gateway 终端节点。终端节点采用 https://some-id.execute-api.us-west-1.amazonaws.com/search-es-api-test 的形式。

  3. 打开 index.html 并尝试运行对 thorhouse 和其他几个术语的搜索。

    
                        针对的示例搜索雷神。

后续步骤

本章只是一个展示概念的起始点。您可以考虑以下修改:

  • 将您自己的数据添加到 Amazon ES 域。

  • 将方法添加到您的 API。

  • 在 Lambda 函数中,修改搜索查询或提高不同的字段。

  • 以不同的方式呈现结果或修改 search.js 以向用户显示不同的字段。