本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
使用 Amazon Elasticsearch Service 创建搜索应用程序
使用 Amazon ES 创建搜索应用程序的一个常用方法是使用 Web 表单将用户查询发送到服务器。然后,您可以授权服务器直接调用 Elasticsearch APIs 并让服务器将请求发送到 Amazon ES。
但是,如果您想编写不依赖服务器的客户端代码,则应针对安全和性能风险作出补偿。不建议允许对 Elasticsearch APIs 进行未签名的公有访问。用户可能会访问不安全的终端节点,或者通过过于广泛的查询(或过多的查询)影响集群性能。
本章提供了一个解决方案:使用 Amazon API Gateway 将用户限制为 Elasticsearch APIs 和 AWS Lambda 的子集以签署从 API 网关 到 Amazon ES 的请求。
标准 API 网关 和 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
使用 API 网关 创建更加受限的 API 简化了与 Elasticsearch _search
API 交互的过程。它还可让您启用安全功能,如 Amazon Cognito 身份验证和请求限制。根据下表创建并部署一个 API。
设置 | Values |
---|---|
API |
类型: 新 API 设置 API 名称:search-es-api 描述:用于搜索 Amazon Elasticsearch Service 域的公共 API 终端节点类型:区域性的 |
资源 |
|
HTTP 方法 |
|
方法请求 |
设置 授权:无 请求验证程序:验证查询字符串参数和标头 需要 API 密钥:false URL 查询字符串参数 名称:q 必需:是 |
集成请求 |
集成类型:Lambda 函数 使用 Lambda 代理集成:是 Lambda 区域: Lambda 函数:search-es-lambda 使用调用方凭证调用:否 凭证缓存:请勿将调用方凭证添加到缓存键 使用默认超时:是 |
阶段 |
名称:search-es-api-test 默认方法限制 启用限制:是 Rate (比率):1000 突增:500 |
这些设置将配置一个 API,该 API 只有一个方法:一个针对终端节点根的 GET
请求 (https://
)。该请求需要单个参数 (some-id
.execute-api.us-west-1
.amazonaws.com/search-es-api-testq
) - 查询字符串要搜索的。调用后,该方法会将请求传递到 Lambda,后者将运行 search-es-lambda
函数。有关更多信息,请参阅在 Amazon API Gateway 中创建 API和在 Amazon API Gateway 中部署 API。
步骤 3:创建 Lambda 函数
在此解决方案中,API 网关 会将请求传递到以下 Python 2.7 Lambda 函数,该函数将查询 Amazon ES 并返回结果:
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 = '' # For example, search-mydomain-id.us-west-1.es.amazonaws.com index = 'movies' url = 'https://' + host + '/' + index + '/_search' # Lambda execution starts here def 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
该函数必须具有以下触发器。
Trigger | API | 部署阶段 | 安全 |
---|---|---|---|
API 网关 | search-es-api | search-es-api-test | 打开 |
由于此示例函数使用的是外部库,您必须创建一个部署程序包并将其上传到 Lambda,才能使代码正常运行。有关创建 Lambda 函数和部署程序包的更多信息,请参阅 https://docs.amazonaws.cn/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html 中的创建部署程序包 (Python)AWS Lambda Developer Guide 和本指南中的。创建 Lambda 部署程序包
步骤 4:修改域访问策略
您的 Amazon ES 域必须允许 Lambda 函数发起针对 movies
索引的 GET
请求。以下策略提供了对整个 movies
索引的 search-es-role
(通过 Lambda 创建)访问:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::123456789012:role/service-role/search-es-role" }, "Action": "es:ESHttpGet", "Resource": "arn:aws:es:us-west-1:123456789012:domain/web/movies/_search" } ] }
有关更多信息,请参阅配置访问策略。
步骤 5:测试 Web 应用程序
测试 Web 应用程序
-
下载 sample-site.zip,解压后在常用文本编辑器中打开
scripts/search.js
。 -
更新
apigatewayendpoint
变量以指向您的 API 网关 终端节点。终端节点采用https://
的形式。some-id
.execute-api.us-west-1
.amazonaws.com/search-es-api-test -
打开
index.html
并尝试运行对 thor、house 和其他几个术语的搜索。
后续步骤
本章只是一个展示概念的起始点。您可以考虑以下修改:
-
将您自己的数据添加到 Amazon ES 域。
-
将方法添加到您的 API。
-
在 Lambda 函数中,修改搜索查询或提高不同的字段。
-
以不同的方式呈现结果或修改
search.js
以向用户显示不同的字段。