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

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

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

使用 Amazon OpenSearch Service 创建搜索应用程序的一个常用方法是使用 Web 表单将用户查询发送到服务器。然后,您可以授权服务器直接调用 OpenSearch API 并让服务器向 OpenSearch Service 发送请求。但是,如果您想编写不依赖服务器的客户端代码,则应针对安全和性能风险作出补偿。不建议允许对 OpenSearch API 的未签名公有访问权限。用户可能会访问不安全的终端节点,或者通过过于广泛的查询(或过多的查询)影响集群性能。

本章为您提供了一个解决方案:使用 Amazon API Gateway 将用户限制到一部分 OpenSearch API 和 Amazon Lambda,并从 API Gateway 到 OpenSearch Service 签署请求。


            搜索应用程序流程图。
注意

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

先决条件

此教程的一个先决条件是 OpenSearch Service 域。如果您还没有域,请按照创建 OpenSearch Service 域中的步骤创建一个域。

步骤 1:为示例数据建立索引

下载 sample-movies.zip,解压它,然后使用 _bulk API 操作将 5000 个文档添加到 movies 索引:

POST https://search-my-domain.us-west-1.es.amazonaws.com/_bulk { "index": { "_index": "movies", "_id": "tt1979320" } } {"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", "_id": "tt1951264" } } {"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"} ...

请注意,上方是一个示例命令,其中包含一小部分可用数据。要执行 _bulk 操作,您需要复制和粘贴 sample-movies 文件的全部内容。有关更多说明,请参阅 选项 2:上传多个文档

您也可以使用以下 curl 命令实现相同的结果:

curl -XPOST -u 'master-user:master-user-password' 'domain-endpoint/_bulk' --data-binary @bulk_movies.json -H 'Content-Type: application/json'

步骤 2:创建并部署 Lambda 函数

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

创建 Lambda 函数

在此解决方案中,API Gateway 会将请求传递到 Lambda 函数,该函数将查询 OpenSearch Service 并返回结果:由于此示例函数使用的是外部库,您需要创建一个部署程序包并将其上传到 Lambda。

创建部署包
  1. 打开命令提示符并创建 my-opensearch-function 项目目录。例如,在 macOS 上,请执行以下操作:

    mkdir my-opensearch-function
  2. 导航到 my-sourcecode-function 项目目录。

    cd my-opensearch-function
  3. 复制以下 Python 示例代码的内容,并且使用名为 opensearch-lambda.py 的新文件将其保存。将您的区域和主机端点添加到文件中。

    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 OpenSearch domain endpoint with https:// and without 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": ["title^4", "plot^2", "actors", "directors"] } } } # Elasticsearch 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
  4. 在新的 package 目录中安装外部库。

    pip3 install --target ./package boto3 pip3 install --target ./package requests pip3 install --target ./package requests_aws4auth
  5. 使用已安装库在根目录下创建部署程序包。以下命令可在项目目录中生成 my-deployment-package.zip 文件。

    cd package zip -r ../my-deployment-package.zip .
  6. opensearch-lambda.py 文件添加到 zip 文件的根目录。

    cd .. zip my-deployment-package.zip opensearch-lambda.py

有关创建 Lambda 函数和部署程序包的更多信息,请参阅 Amazon Lambda 开发人员指南中的使用 .zip 文件归档部署 Python Lambda 函数和本指南中的 创建 Lambda 部署程序包

使用 Lambda 控制台创建函数

  1. 导航到 Lambda 控制台:https://console.aws.amazon.com/lambda/home。在左侧导航窗格中,选择函数

  2. 选择创建函数

  3. 配置以下字段:

    • 函数名称:opensearch-function

    • 运行时:Python 3.9

    • 架构:x86_64

    保留所有其他默认选项,然后选择创建函数

  4. 在函数摘要页面的代码源部分,选择从下拉列表中上传,然后选择 .zip 文件。找到您创建的 my-deployment-package.zip 文件,然后选择保存

  5. 处理程序是函数代码中处理事件的方法。在运行时设置下,选择编辑,根据 Lambda 函数所在的部署包中的文件名更改处理程序名称。鉴于您的文件名为 opensearch-lambda.py,请将处理程序重命名为 opensearch-lambda.lambda_handler。有关更多信息,请参阅 Python 中的 Lambda 函数处理程序中的

步骤 3:在 API Gateway 中创建 API

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

创建和配置 API

使用 API Gateway 控制台创建 API

  1. 通过以下网址导航到 API Gateway 控制台:https://console.aws.amazon.com/apigateway/home。在左侧导航窗格中,选择 APIs

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

  3. 在下一页中,找到新建 API 部分,确保选中新建 API

  4. 配置以下字段:

    • API 名称:opensearch-api

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

    • 端点类型:区域

  5. 选择创建 API

  6. 选择操作创建方法

  7. 在下拉菜单中选择GET,然后单击复选标记进行确认。

  8. 配置以下设置,然后选择保存

设置
集成类型 Lambda 函数
使用 Lambda 代理集成 可以
Lambda 区域 us-west-1
Lambda 函数 opensearch-lambda
使用原定设置超时 可以

配置该方法请求

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

设置
授权 NONE
请求验证器

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

必需的 API 密钥 false

URL 查询字符串参数下,选择添加查询字符串并配置以下参数:

设置
姓名 q
必需

可以

部署 API 并配置阶段

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

  1. 选择操作部署 API

  2. 对于部署阶段选择新阶段并将阶段命名为 opensearch-api-test

  3. 选择部署

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

设置
启用限制 可以
费率

1000

突增 500

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

步骤 4:(可选)修改域访问策略

OpenSearch Service 域必须允许 Lambda 函数向 movies 索引发出 GET 请求。如果您的域具有已启用精细访问控制的开放访问策略,则可以将其保持原样:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": "es:*", "Resource": "arn:aws:es:us-west-1:123456789012:domain/domain-name/*" } ] }

您也可以选择建立更加精细的域访问策略。例如,以下最低策略提供了对整个 movies 索引的 opensearch-lambda-role(通过 Lambda 创建)访问:要获取 Lambda 自动创建的角色的确切名称,请转到 Amazon Identity and Access Management(IAM) 控制台,请选择角色,并搜索 “lambda”。

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

如果您为域启用了精细访问控制,则还需要在 OpenSearch 控制面板中将角色映射到用户,否则就会看到权限错误。

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

映射 Lambda 角色(如果使用精细访问控制)

精细访问控制将在您能测试应用程序之前引入一个额外步骤。即使您将 HTTP 基本身份验证用于所有其他目的,也需要将 Lambda 角色映射到用户,否则您将看到权限错误。

  1. 导航到域的 OpenSearch 控制面板 URL。

  2. 从主菜单中,选择安全角色,然后选择 all_access 链接和需要将 Lambda 角色映射到的角色。

  3. 选择映射的用户管理映射

  4. Backend roles(后端角色)下,添加 Lambda 角色的 Amazon 资源名称(ARN)。ARN 应采用 arn:aws:iam::123456789123:role/service-role/opensearch-lambda-role-1abcdefg 形式。

  5. 选择映射并确认在映射的用户下显示的用户或角色。

步骤 5:测试 Web 应用程序

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

  2. 更新 apigatewayendpoint 变量以指向您的 API Gateway 端点,并在给定路径末尾添加反斜线。您可以选择阶段,然后选择 API 的名称,即可在 API Gateway 中快速找到端点。apigatewayendpoint 变量应采用 https://some-id.execute-api.us-west-1.amazonaws.com/opensearch-api-test/ 形式。

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

    
                        一个对 thor 的示例搜索。

排除 CORS 错误

尽管 Lambda 函数在响应中包含支持 CORS 的内容,但您仍可能会看到以下错误:

Access to XMLHttpRequest at '<api-gateway-endpoint>' from origin 'null' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present in the requested resource.

如果,请尝试以下操作:

  1. 在 GET 资源上启用 CORS。在 Advanced (高级) 西方,设置 Access-Control-Allow-Credentials'true'

  2. 在 API Gateway 中重新部署 API (Action (操作)Deploy API (部署 API))。

  3. 删除并重新添加 Lambda 函数触发器。重新添加,选择添加触发器并创建调用函数的 HTTP 端点。该触发器必须具有以下配置:

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

后续步骤

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

  • 将您自己的数据添加到 OpenSearch Service 域。

  • 将方法添加到您的 API。

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

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