Amazon Elasticsearch Service
开发人员指南 (API 版本 2015-01-01)
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 Amazon AWS 入门

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

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

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

本章为您提供了一个解决方案:使用 Amazon API Gateway 将用户限制到一部分 Elasticsearch API,并使用 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。

设置
API

类型:新 API

设置

API 名称:search-es-api

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

终端节点类型:区域

资源

/

HTTP 方法

GET

方法请求

设置

授权:无

请求验证器:验证查询字符串参数和标头

需要 API 密钥:false

URL 查询字符串参数

名称:q

必需:是

集成请求

集成类型:Lambda 函数

使用 Lambda 代理集成:是

Lambda 区域:us-west-1

Lambda 函数:search-es-lambda

使用调用方凭证进行调用:否

凭证缓存:不将调用方凭证添加到缓存键

使用默认超时:是

阶段

名称:search-es-api-test

默认方法限制

启用限制:是

速率:1000

突增:500

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

该函数必须具有以下触发器。

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

有关创建 Lambda 函数和部署程序包的更多信息,请参阅 AWS Lambda Developer Guide 中的创建部署程序包 (Python) 和本指南中的创建 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 应用程序

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

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

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

    
                        一个对 thor 的示例搜索。

后续步骤

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

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

  • 将方法添加到您的 API。

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

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