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

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

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

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

本章介绍一个解决方案:使用 Amazon API Gateway 将用户限制为其中的一个子集, OpenSearch APIs 并 Amazon Lambda 对从 API Gateway 到 OpenSearch 服务的请求进行签名。

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

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

先决条件

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

步骤 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 服务并返回结果。由于此示例函数使用的是外部库,您需要创建一个部署程序包并将其上传到 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/在左侧导航窗格中,选择函数

  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. https://console.aws.amazon.com/apigateway/家中导航到 API Gateway 控制台。在左侧导航窗格中,选择APIs

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

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

  4. 配置以下字段:

    • API 名称:opensearch-api

    • 描述:用于搜索亚马逊 OpenSearch 服务域名的公共 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 服务域必须允许 Lambda 函数向GET索引发出请求。movies如果您的域具有已启用精细访问控制的开放访问策略,则可以将其保持原样:

JSON
{ "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”。

JSON
{ "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 执行角色权限

除了配置域访问策略外,您还必须确保 Lambda 执行角色具有访问您的 OpenSearch 服务域所必需的 IAM 权限。Lambda 函数需要特定的权限,具体取决于您使用的是托管域还是无 OpenSearch 服务集合。

对于托管 OpenSearch 服务域:

将以下 IAM 策略附加到您的 Lambda 执行角色以允许其向您的 OpenSearch 服务域发出请求:

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

对于无服务器 OpenSearch 服务集合:

如果您使用的是无服务器 OpenSearch 服务,请将以下 IAM 策略附加到您的 Lambda 执行角色:

JSON
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "aoss:*", "Resource": "arn:aws:aoss:us-west-1:123456789012:collection/collection-id" } ] }

要将这些策略附加到您的 Lambda 执行角色,请执行以下操作:

  1. 导航到 https://console.aws.amazon.com/iam/ 的 IAM 控制台。

  2. 选择角色并搜索您的 Lambda 执行角色(通常命名opensearch-lambda-role-xxxxxxxx)。

  3. 选择添加权限,然后选择创建内联策略

  4. 选择 JSON 选项卡并粘贴上面的相应策略,将占位符值替换为实际资源 ARNs。

  5. 选择查看策略,提供类似的名称OpenSearchAccess,然后选择创建策略

注意

如果没有这些 IAM 权限,即使域访问策略允许请求,您的 Lambda 函数在尝试查询您的 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 服务域。

  • 将方法添加到您的 API。

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

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