教學:使用 Amazon OpenSearch 服務建立搜尋應用程式 - Amazon OpenSearch Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

教學:使用 Amazon OpenSearch 服務建立搜尋應用程式

使用 Amazon Ser OpenSearch vice 建立搜尋應用程式的常用方法是使用網頁表單將使用者查詢傳送到伺服器。然後,您可以授權服務器直接調 OpenSearch 用 API,並讓服務器將請求發送到 OpenSearch 服務。但是如果您想要編寫不依賴伺服器的用戶端程式碼,您應彌補安全性和效能風險。不建議允許未簽署的公開存取 OpenSearch API。使用者可能會透過過於廣泛的查詢 (或太多查詢) 存取不安全的端點或影響叢集效能。

本章介紹一個解決方案:使用 Amazon API Gateway 將使用者限制為 OpenSearch API 的子集,並AWS Lambda簽署從 API Gateway 到 OpenSearch 服務的請求。

搜索應用程式流程圖。
注意

標準 API Gateway​ 和 ​Lambda 定價適用,但在此教學課程的限制使用量之內,成本應微乎其微。

必要條件

本教學課程的先決條件是 OpenSearch 服務網域。如果您還沒有服務網域,請依照建立 OpenSearch 服務網域中的步驟建立服務網域

步驟 1:索引範例資料

下載 sample-movies.zip、進行解壓縮,然後使用 _bulk​ API 操作來將 5,000 個文件新增到 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 函數和部署套件的詳細資訊,請參閱 AWS Lambda 開發人員指南中的使用 .zip 封存檔部署 Python Lambda 函數以及本指南中的 建立 Lambda 部署套件

若要使用 Lambda 主控台建立函數

  1. 瀏覽至 Lambda 主控台,網址為 https://console.aws.amazon.com/lambda/home。在左側導覽窗格中,選擇 [函數]。

  2. 選取 Create function (建立函數)。

  3. 設定下列欄位:

    • 功能名稱:打開搜索功能

    • 執行階段: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。在左側導覽窗格中,選擇 [API]。

  2. 找到 REST API (非私有) 並選擇 Build (建置)。

  3. 在下一頁上,找到「建立新 API」區段,並確定已選取「新建 API」。

  4. 設定下列欄位:

    • API 名稱:opensearch-api

    • 說明:用於搜索 Amazon OpenSearch 服務域的公共 API

    • 端點類型:區域

  5. 選擇建立 API

  6. 選擇 Actions (動作) 和 Create Method (建立方法)。

  7. 在下拉式選單中選擇 GET,然後按一下核取記號以確認。

  8. 進行下列設定,然後選擇 Save (儲存):

設定 Value
整合類型 Lambda 函數
使用 Lambda 代理整合
Lambda 區域 us-west-1
Lambda 函數 opensearch-lambda
使用預設逾時

設定方法請求

選擇 Method Request (方法請求),然後進行下列設定:

設定 Value
授權 NONE
請求驗證程式

驗證查詢字串參數與標頭

需要 API 金鑰 false

在「URL 查詢字串參數」下,選擇「新增查詢字串」並設定下列參數:

設定 Value
名稱 q
必要

部署 API 並設定階段

API Gateway 主控台可讓您透過建立部署並將它與全新或現有階段建立關聯來部署 API。

  1. 選擇 Actions (動作) 和 Deploy API (部署 API)。

  2. 對於 Deployment stage (部署階段),選擇 New Stage (新增階段) 並將階段命名為 opensearch-api-test

  3. 選擇部署

  4. 在階段編輯器中進行下列設定,然後選擇 Save Changes (儲存變更):

設定 Value
啟用調節
速率

1000

爆量 500

這些設定會設定僅有一個方法的 API:GET 對端點根進行要求 (https://some-id.execute-api.us-west-1.amazonaws.com/search-es-api-test)。要求需要單一參數 (q),要搜尋的查詢字串。呼叫時,方法會將請求傳遞至 Lambda,它會執行 ​opensearch-lambda 函數。如需詳細資訊,請參閱在 Amazon API Gateway 中建立 API在 Amazon API Gateway 中部署 REST API

步驟 4:(選用) 修改網域存取政策

您的 OpenSearch 服務網域必須允許 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 自動建立之角色的確切名稱,請移至 AWS Identity and Access Management (IAM) 主控台,選擇 Roles (角色),並搜索 "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. 選擇 Mapped users (已映射的使用者)、Manage mapping (管理映射)。

  4. Backend roles (後端角色) 下方,新增 Lambda 角色的 Amazon Resource Name (ARN)。ARN 應採取的arn:aws:iam::123456789123:role/service-role/opensearch-lambda-role-1abcdefg形式.

  5. 選擇 Map (映射),並確認使用者或角色顯示在 Mapped users (已映射的使用者) 中。

步驟 5:測試 Web 應用程式

若要測試 web 應用程式
  1. 下載 sample-site.zip,將其解壓縮並使用您最愛的文字編輯器將 scripts/search.js​ 開啟。

  2. 更新apigatewayendpoint變數以指向您的 API Gateway 端點,並在指定路徑的末尾新增反斜線。您可以透過選擇 Stages (階段),然後選取 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 (Actions (動作)、Deploy API (部署 API))。

  3. 刪除並重新新增您的 Lambda 函數觸發程序。添加重新添加它,選擇添加觸發器並創建調用您的函數的 HTTP 端點。觸發必須具有以下組態:

    觸發條件 API 部署階段 安全
    API 閘道 opensearch-api opensearch-api-test 開啟

後續步驟

本章只是展縣概念的起點。您可以考慮以下修改:

  • 將您自己的資料新增至 OpenSearch 服務網域。

  • 將方法新增至 API

  • 在 Lambda​ 函數中,修改搜尋查詢或提升不同的欄位。

  • 樣式結果不同或修改 search.js​ 來向使用者顯示不同的欄位。