

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

# Amazon OpenSearch Service 教學課程
<a name="tutorials"></a>

本章包含幾個從開始到結束的教學課程，以便使用 Amazon OpenSearch Service，這包括如何遷移到服務、建置簡單的搜尋應用程式以及在 OpenSearch Dashboards 中建立視覺效果。

**Topics**
+ [教學課程：在 Amazon OpenSearch Service 中建立和搜尋文件](quick-start.md)
+ [教學課程：遷移至 Amazon OpenSearch Service](migration.md)
+ [教學課程：使用 Amazon OpenSearch Service 建立一個搜尋應用程式](search-example.md)
+ [教學課程：使用 OpenSearch Service 和 OpenSearch Dashboards，將客戶支援呼叫視覺化](walkthrough.md)

# 教學課程：在 Amazon OpenSearch Service 中建立和搜尋文件
<a name="quick-start"></a>

在本教學課程中，您可學習如何在 Amazon OpenSearch Service 中建立和搜尋文件。您可以 JSON 文件格式將資料新增至索引。OpenSearch Service 會圍繞您新增的第一個文件建立索引。

本教學課程說明如何發出 HTTP 請求以建立文件、自動產生文件 ID，以及如何對文件執行基本搜尋和進階搜尋。

**注意**  
本教程課程使用具有開放存取權的網域。為了實現最高等級的安全性，我們建議您將網域放入虛擬私有雲端 (VPC) 內。

## 先決條件
<a name="quick-start-prereqs"></a>

本教學課程具備下列先決條件：
+ 您必須擁有 AWS 帳戶。
+ 您必須擁有作用中的 OpenSearch Service 網域。

## 將文件新增至索引
<a name="quick-start-create"></a>

若要將文件新增至索引，您可以使用任何 HTTP 工具，例如 [Postman](https://www.getpostman.com/)、cURL 或 OpenSearch Dashboards 主控台。這些範例假設您正在使用 OpenSearch Dashboards 中的開發人員主控台。如果您使用其他工具，請視需要提供完整的 URL 和憑證進行相應調整。

**若要將文件新增至索引**

1. 導覽至您網域的 OpenSearch Dashboards URL。您可以在 OpenSearch Service 主控台網域的儀表板上找到 URL。URL 遵循以下格式：

   ```
   domain-endpoint/_dashboards/
   ```

1. 使用您的主要使用者名稱和密碼登入。

1. 開啟左側導覽面板並選擇 **Dev Tools** (開發工具)。

1. 用於建立新資源的 HTTP 動詞為 PUT，可使用它來建立新文件和索引。在主控台中，輸入以下命令：

   ```
   PUT fruit/_doc/1
   {
     "name":"strawberry",
     "color":"red"
   }
   ```

   `PUT` 請求會建立一個名為 *fruit* 的索引，並將 ID 為 1 的單一文件新增至該索引。它產生如下回應：

   ```
   {
     "_index" : "fruit",
     "_type" : "_doc",
     "_id" : "1",
     "_version" : 1,
     "result" : "created",
     "_shards" : {
       "total" : 2,
       "successful" : 2,
       "failed" : 0
     },
     "_seq_no" : 0,
     "_primary_term" : 1
   }
   ```

## 建立自動產生的 ID
<a name="quick-start-id"></a>

OpenSearch Service 可以自動為您的文件產生一個 ID。產生 ID 的命令使用 POST 請求而非 PUT 請求，並且不需要文件 ID (與之前的請求相比)。

在開發人員主控台中輸入以下請求：

```
POST veggies/_doc
{
  "name":"beet",
  "color":"red",
  "classification":"root"
}
```

此請求會建立一個名為 *veggies* 的索引並將文件新增至索引。它產生如下回應：

```
{
  "_index" : "veggies",
  "_type" : "_doc",
  "_id" : "3WgyS4IB5DLqbRIvLxtF",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}
```

請注意，回應中的其他`_id`欄位，表示 ID 已自動建立。

**注意**  
您在 URL 的 `_doc` 後面沒有提供任何內容，ID 通常會出現在該位置。因為您要使用產生的 ID 建立文件，所以尚未提供 ID。這預留用於更新。

## 使用 POST 命令更新文件
<a name="quick-start-update"></a>

若要更新文件，請使用帶有 ID 號的 HTTP `POST` 命令。

首先，建立 ID 為 `42` 的文件：

```
POST fruits/_doc/42
{
  "name":"banana",
  "color":"yellow"
}
```

然後使用該 ID 更新文件：

```
POST fruits/_doc/42
{
  "name":"banana",
  "color":"yellow",
  "classification":"berries"
}
```

此命令使用新欄位 `classification` 更新文件。它產生如下回應：

```
{
  "_index" : "fruits",
  "_type" : "_doc",
  "_id" : "42",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}
```

**注意**  
如果您嘗試更新不存在的文件，OpenSearch Service 會建立該文件。

## 執行大量動作
<a name="quick-start-bulk"></a>

您可以使用 `POST _bulk` API 操作對一個請求中的一個或多個索引執行多個動作。大量動作命令採用下列格式：

```
POST /_bulk
<action_meta>\n
<action_data>\n
<action_meta>\n
<action_data>\n
```

每個動作需要兩行 JSON。首先，您要提供動作說明或中繼資料。在下一行中提供該資料。每部分由換行符號 (\$1n) 分隔。插入的動作描述可能如下所示：

```
{ "create" : { "_index" : "veggies", "_type" : "_doc", "_id" : "7" } }
```

包含資料的下一行可能如下所示：

```
{ "name":"kale", "color":"green", "classification":"leafy-green" }
```

中繼資料和資料結合在一起，表示大量操作中的單一動作。您可以在一個請求中執行許多操作，如下所示：

```
POST /_bulk
{ "create" : { "_index" : "veggies", "_id" : "35" } }
{ "name":"kale", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "36" } }
{ "name":"spinach", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "37" } }
{ "name":"arugula", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "38" } }
{ "name":"endive", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "39" } }
{ "name":"lettuce", "color":"green", "classification":"leafy-green" }
{ "delete" : { "_index" : "vegetables", "_id" : "1" } }
```

請注意，最後一個動作是 `delete`。`delete` 動作之後沒有資料。

## 搜尋文件
<a name="quick-start-search"></a>

現在您的叢集中存在資料，您可以搜尋它。例如，您可能想要搜尋所有根莖類蔬菜，或取得所有綠葉蔬菜的計數，或者尋找每小時記錄的錯誤數量。

**基本搜尋**

基本搜尋如下所示：

```
GET veggies/_search?q=name:l*
```

該請求會產生一個包含萵苣文件的 JSON 回應。

**進階搜尋**

您可以在請求主體中以 JSON 格式提供查詢選項，以執行更進階的搜尋：

```
GET veggies/_search
{
  "query": {
    "term": {
      "name": "lettuce"
    }
  }
}
```

此範例還會產生一個帶有萵苣文件的 JSON 回應。

**排序**

您可以使用排序功能來執行更多此類查詢。首先，您需要重新建立索引，因為自動欄位映射選擇了預設情況下無法排序的類型。傳送下列請求，以刪除並重新建立索引：

```
DELETE /veggies

PUT /veggies
{
   "mappings":{
      "properties":{
         "name":{
            "type":"keyword"
         },
         "color":{
            "type":"keyword"
         },
         "classification":{
            "type":"keyword"
         }
      }
   }
}
```

然後用資料重新填入索引：

```
POST /_bulk
{ "create" : { "_index" : "veggies", "_id" : "7"  } }
{ "name":"kale", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "8" } }
{ "name":"spinach", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "9" } }
{ "name":"arugula", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "10" } }
{ "name":"endive", "color":"green", "classification":"leafy-green" }
{ "create" : { "_index" : "veggies", "_id" : "11" } }
{ "name":"lettuce", "color":"green", "classification":"leafy-green" }
```

現在，您可以使用排序進行搜尋。此請求會按照分類新增遞增排序：

```
GET veggies/_search
{
  "query" : {
    "term": { "color": "green" }
  },
  "sort" : [
      "classification"
  ]
}
```

## 相關資源
<a name="quick-start-resources"></a>

如需詳細資訊，請參閱下列資源：
+ [Amazon OpenSearch Service 入門](gsg.md)
+ [在 Amazon OpenSearch Service 中建立資料索引](indexing.md)
+ [在 Amazon OpenSearch Service 中搜尋資料](searching.md)

# 教學課程：遷移至 Amazon OpenSearch Service
<a name="migration"></a>

索引快照是將自我管理的 OpenSearch 或舊版 Elasticsearch 叢集遷移至 Amazon OpenSearch Service 的常用方法。此程序大致包含下列步驟：

1. 建立現有叢集的快照，然後將快照上傳至 Amazon S3 儲存貯體。

1. 建立 OpenSearch Service 網域

1. 授與 OpenSearch Service 存取儲存貯體的許可，並確保您擁有使用快照的許可。

1. 在 OpenSearch Service 網域上還原快照。

此逐步解說提供更詳細的步驟和替代選項，如適用。

## 建立並上傳快照
<a name="migration-take-snapshot"></a>

雖然您可以使用儲存[庫-s3](https://docs.opensearch.org/latest/opensearch/snapshot-restore/#amazon-s3) 外掛程式直接將快照擷取到 S3，但您必須在每個節點上安裝外掛程式、調整 `opensearch.yml`(`elasticsearch.yml`如果使用 Elasticsearch 叢集）、重新啟動每個節點、新增您的 AWS 憑證，最後再拍攝快照。外掛程式是適合持續使用或遷移較大型叢集的絕佳選擇。

對於較小的叢集，一次性方法是拍攝[共用檔案系統快照](https://docs.opensearch.org/latest/opensearch/snapshot-restore/#shared-file-system)，然後使用 AWS CLI 將其上傳至 S3。如果您已經有快照，請跳至步驟 4。

****若要建立快照並上傳至 Amazon S3****

1. 將 `path.repo` 設定新增至所有節點上的 `opensearch.yml` (或 `Elasticsearch.yml`)，然後重新啟動每個節點。

   ```
   path.repo: ["/my/shared/directory/snapshots"]
   ```

1. 註冊[快照儲存庫](https://opensearch.org/docs/latest/opensearch/snapshot-restore/#register-repository)，此為建立快照前所需。儲存庫只是一個儲存位置：共用檔案系統、Amazon S3、Hadoop 分散式檔案系統 (HDFS) 等。在此情況下，我們將使用共用檔案系統 ("fs")：

   ```
   PUT _snapshot/my-snapshot-repo-name
   {
     "type": "fs",
     "settings": {
       "location": "/my/shared/directory/snapshots"
     }
   }
   ```

1. 建立快照：

   ```
   PUT _snapshot/my-snapshot-repo-name/my-snapshot-name
   {
     "indices": "migration-index1,migration-index2,other-indices-*",
     "include_global_state": false
   }
   ```

1. 安裝 [AWS CLI](https://aws.amazon.com/cli/)，然後執行 `aws configure` 以新增您的登入資料。

1. 瀏覽至快照目錄。然後執行下列命令以建立新的 S3 儲存貯體，並將快照目錄的內容上傳至該儲存貯體：

   ```
   aws s3 mb s3://amzn-s3-demo-bucket --region us-west-2
   aws s3 sync . s3://amzn-s3-demo-bucket --sse AES256
   ```

   視快照大小和網際網路連線速度而定，此操作可能需要一段時間。

## 建立網域
<a name="migration-create-domain"></a>

雖然主控台是建立網域最簡單的方式，但在這種情況下，您已經開啟終端機並 AWS CLI 安裝 。修改下列命令即可建立符合您需求的網域：

```
aws opensearch create-domain \
  --domain-name migration-domain \
  --engine-version OpenSearch_1.0 \
  --cluster-config InstanceType=c5.large.search,InstanceCount=2 \
  --ebs-options EBSEnabled=true,VolumeType=gp2,VolumeSize=100 \
  --node-to-node-encryption-options Enabled=true \
  --encryption-at-rest-options Enabled=true \
  --domain-endpoint-options EnforceHTTPS=true,TLSSecurityPolicy=Policy-Min-TLS-1-2-2019-07 \
  --advanced-security-options Enabled=true,InternalUserDatabaseEnabled=true,MasterUserOptions='{MasterUserName=master-user,MasterUserPassword=master-user-password}' \
  --access-policies '{"Version": "2012-10-17",		 	 	 "Statement":[{"Effect":"Allow","Principal": {"AWS": "arn:aws:iam::aws-region:user/UserName"},"Action":["es:ESHttp*"],"Resource":"arn:aws:es:aws-region:111122223333:domain/migration-domain/*"}]}' \
  --region aws-region
```

若未經修改，此命令會建立具有兩個資料節點的網際網路存取網域，每個節點都有 100 GiB 的儲存空間。它也會啟用具有 HTTP 基本身分驗證和所有加密設定的[精細存取控制](fgac.md)。如果您需要更進階的安全組態 (例如 VPC)，請使用 OpenSearch Service 主控台。

發出命令之前，請先變更網域名稱、主要使用者登入資料和帳戶號碼。指定您用於 S3 儲存貯體 AWS 區域 的相同 ，以及與您的快照相容的 OpenSearch/Elasticsearch 版本。

**重要**  
快照只能正向相容，而且只能往前一個主要版本。例如，您無法從 Elasticsearch 7.x 叢集上的 OpenSearch 1.*x* 叢集還原快照，只能從 OpenSearch 1.*x* 或 2.*x* 叢集還原快照。**次要版本也很重要。您無法在 5.3.2 OpenSearch Service 網域上從自我管理的 5.3.3 叢集中還原快照。我們建議您選擇您的快照支援的 OpenSearch 或 Elasticsearch 的最新版本。如需相容版本的表格，請參閱[使用快照來遷移資料](snapshot-based-migration.md)。

## 提供許可以存取 S3 儲存貯體。
<a name="migration-permissions"></a>

在 AWS Identity and Access Management (IAM) 主控台中，[建立具有下列許可和信任關係的角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html)。 [https://docs.aws.amazon.com/IAM/latest/UserGuide/roles-managingrole-editing-console.html#roles-managingrole_edit-trust-policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/roles-managingrole-editing-console.html#roles-managingrole_edit-trust-policy)在建立角色時，選擇 **S3** 作為 **AWS Service**。將角色命名為 `OpenSearchSnapshotRole` 以便輕鬆找到。

**許可**

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [{
      "Action": [
        "s3:ListBucket"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::amzn-s3-demo-bucket"
      ]
    },
    {
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Effect": "Allow",
      "Resource": [
        "arn:aws:s3:::amzn-s3-demo-bucket/*"
      ]
    }
  ]
}
```

------

**信任關係**

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [{
      "Effect": "Allow",
      "Principal": {
        "Service": "es.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```

------

然後授予您的個人 IAM 角色許可，以擔任 `OpenSearchSnapshotRole`。建立下列政策，並[將它連接](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_manage-attach-detach.html)到您的身分：

**許可**

------
#### [ JSON ]

****  

```
{
  "Version":"2012-10-17",		 	 	 
  "Statement": [{
      "Effect": "Allow",
      "Action": "iam:PassRole",
      "Resource": "arn:aws:iam::123456789012:role/OpenSearchSnapshotRole"
    }
  ]
}
```

------

### 映射 OpenSearch Dashboards 中的快照角色 (如果使用精細存取控制)
<a name="migration-snapshot-role"></a>

如果您已啟用[精細存取控制](fgac.md#fgac-mapping)，即使您將 HTTP 基本身分驗證用於所有其他目的，您也需要將 `manage_snapshots` 角色映射至 IAM 角色，以便您可以使用快照。

**若要為您的身分授予許可以便使用快照**

1. 使用您在建立 OpenSearch Service 網域時指定的主要使用者憑證登入 Dashboards。您可以在 OpenSearch Service 主控台中找到 Dashboards URL。其格式為 `https://domain-endpoint/_dashboards/`。

1. 從主選單中選擇 **Security** (安全性)、**Roles** (角色)，然後選取 **manage\$1snapshots** 角色。

1. 選擇 **Mapped users** (已映射的使用者)、**Manage mapping** (管理映射)。

1. 在適當的欄位中新增您的個人 IAM 角色的網域 ARN。ARN 採用下列其中一種格式：

   ```
   arn:aws:iam::123456789123:user/user-name
   ```

   ```
   arn:aws:iam::123456789123:role/role-name
   ```

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

## 還原快照
<a name="migration-restore"></a>

此時，您有兩種方式可存取 OpenSearch Service 網域：使用主要使用者憑證進行 HTTP 基本身分驗證，或使用 IAM 憑證進行 AWS 身分驗證。由於快照使用 Amazon S3，它沒有主要使用者的概念，因此您必須使用 IAM 憑證向您的 OpenSearch Service 網域註冊快照儲存庫。

大多數程式設計語言都有程式庫來協助簽署請求，但更簡單的方法是使用 [Postman](https://www.postman.com/downloads/) 之類的工具，並將您的 IAM 登入資料放入**授權**區段。

![\[Postman interface showing Authorization settings for AWS API request with Signature type.\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/migration2.png)


**還原快照**

1. 無論您選擇如何簽署請求，第一步都是註冊儲存庫：

   ```
   PUT _snapshot/my-snapshot-repo-name
   {
     "type": "s3",
     "settings": {
       "bucket": "amzn-s3-demo-bucket",
       "region": "us-west-2",
       "role_arn": "arn:aws:iam::123456789012:role/OpenSearchSnapshotRole"
     }
   }
   ```

1. 然後列出儲存庫中的快照，找到您要還原的快照。此時，您可以繼續使用 Postman，或切換到 [curl](https://curl.haxx.se/) 等工具。

   **速記**

   ```
   GET _snapshot/my-snapshot-repo-name/_all
   ```

   **curl**

   ```
   curl -XGET -u 'master-user:master-user-password' https://domain-endpoint/_snapshot/my-snapshot-repo-name/_all
   ```

1. 還原快照。

   **速記**

   ```
   POST _snapshot/my-snapshot-repo-name/my-snapshot-name/_restore
   {
     "indices": "migration-index1,migration-index2,other-indices-*",
     "include_global_state": false
   }
   ```

   **curl**

   ```
   curl -XPOST -u 'master-user:master-user-password' https://domain-endpoint/_snapshot/my-snapshot-repo-name/my-snapshot-name/_restore \
     -H 'Content-Type: application/json' \
     -d '{"indices":"migration-index1,migration-index2,other-indices-*","include_global_state":false}'
   ```

1. 最後，確認索引是否已依照預期還原。

   **速記**

   ```
   GET _cat/indices?v
   ```

   **curl**

   ```
   curl -XGET -u 'master-user:master-user-password' https://domain-endpoint/_cat/indices?v
   ```

此時，遷移即已完成。您可以設定用戶端以使用新的 OpenSearch Service 端點，[調整網域大小](sizing-domains.md)以符合您的工作負載，檢查索引的碎片計數，切換到 [IAM 主要使用者](fgac.md#fgac-concepts)，或開始在 OpenSearch Dashboards 中建置視覺效果。

# 教學課程：使用 Amazon OpenSearch Service 建立一個搜尋應用程式
<a name="search-example"></a>

使用 ​Amazon OpenSearch Service 建立搜尋應用程式的常見方法是使用 web 表單將使用者查詢傳送到伺服器。接著，您可以授權伺服器直接呼叫 ​OpenSearch API 並讓伺服器將請求傳送至 OpenSearch Service。但是如果您想要編寫不依賴伺服器的用戶端程式碼，您應彌補安全性和效能風險。允許對 ​OpenSearch API 的未簽署、公開存取是不明智的做法。使用者可能會透過過於廣泛的查詢 (或太多查詢) 存取不安全的端點或影響叢集效能。

本章提供解決方案：使用 Amazon API Gateway 將使用者限制為 OpenSearch APIs的子集 AWS Lambda ，並簽署從 API Gateway 到 OpenSearch Service 的請求。

![\[搜索應用程式流程圖。\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/search-application-diagram.png)


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

## 先決條件
<a name="search-example-prereq"></a>

此教學的先決條件是 OpenSearch Service​ 網域。如果沒有，請遵循[建立 OpenSearch Service 網域](gsgcreate-domain.md)中的步驟建立一個。

## 步驟 1：索引範例資料
<a name="search-example-index"></a>

下載 [sample-movies.zip](samples/sample-movies.zip)、進行解壓縮，然後使用 [\$1bulk](https://opensearch.org/docs/latest/api-reference/document-apis/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：上傳多個文件](gsgupload-data.md#gsgmultiple-document)。

您也可以使用下列 curl 命令來達成相同的結果：

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

## 步驟 2：建立和部署 Lambda 函數
<a name="search-example-lambda"></a>

在 API Gateway 中建立 API 之前，請先建立傳遞請求的 Lambda 函數。

### 建立 Lambda 函式
<a name="sample-lamdba-python"></a>

在此解決方案中，API Gateway 會將請求傳遞至 Lambda 函數，該函數會查詢 OpenSearch Service 並傳回結果。由於此範例函數使用外部程式庫，您需要建立部署套件並將其上傳至 Lambda。

**建立部署套件**

1. 開啟命令提示字元並建立 `my-opensearch-function` 專案目錄。例如，在 macOS 上：

   ```
   mkdir my-opensearch-function
   ```

1. 導覽至 `my-sourcecode-function` 專案目錄。

   ```
   cd my-opensearch-function
   ```

1. 複製下列範例 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
   ```

1. 將外部程式庫安裝到新的`package`目錄。

   ```
   pip3 install --target ./package boto3
   pip3 install --target ./package requests
   pip3 install --target ./package requests_aws4auth
   ```

1. 在根目錄中使用已安裝的程式庫建立部署套件。下列命令會在您的專案目錄中產生`my-deployment-package.zip`檔案。

   ```
   cd package
   zip -r ../my-deployment-package.zip .
   ```

1. 將 `opensearch-lambda.py` 檔案新增至 zip 檔案的根目錄。

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

如需建立 Lambda 函數和部署套件的詳細資訊，請參閱 *AWS Lambda 開發人員指南*中的[使用 .zip 封存檔部署 Python Lambda 函數](https://docs.aws.amazon.com/lambda/latest/dg/lambda-python-how-to-create-deployment-package.html)以及本指南中的 [建立 Lambda 部署套件](integrations-s3-lambda.md#integrations-s3-lambda-deployment-package)。

使用 Lambda 主控台建立函數

1. 導覽至位於 https：//[https://console.aws.amazon.com/lambda/home](https://console.aws.amazon.com/lambda/home ) 的 Lambda 主控台。在左側導覽窗格中，選擇**函數**。

1. 選取 **Create function** (建立函式)。

1. 設定下列欄位：
   + 函數名稱：openearch-function
   + 執行時間：Python 3.9
   + 架構：x86\$164

   保留所有其他預設選項，然後選擇**建立函數**。

1. 在函數摘要頁面的**程式碼來源**區段中，選擇**從下拉式清單上傳**，然後選取 **.zip 檔案**。找到您建立`my-deployment-package.zip`的檔案，然後選擇**儲存**。

1. *處理常式*是函數程式碼中處理事件的方法。在**執行時間設定**下，選擇**編輯**，並根據 Lambda 函數所在的部署套件中的檔案名稱變更處理常式名稱。由於您的檔案名為 `opensearch-lambda.py`，請將處理常式重新命名為 `opensearch-lambda.lambda_handler`。如需詳細資訊，請參閱 [Python 中的 Lambda 函數處理常式](https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html)。

## 步驟 3：在 API Gateway 中建立 API
<a name="search-example-api"></a>

使用 ​API Gateway 來建立更為有限的 API 並簡化與 OpenSearch `_search` API 互動的程序。API Gateway 可啟用安全性功能，例如 Amazon Cognito 身分驗證和請求調節。請執行下列步驟，來建立和部署 API：

### 建立和設定 API
<a name="create-api"></a>

若要使用 API Gateway 主控台建立 API

1. 導覽至 API Gateway 主控台，網址為 https：//[https://console.aws.amazon.com/apigateway/home](https://console.aws.amazon.com/apigateway/home )。在左側導覽窗格中，選擇 **APIs**。

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

1. 在下列頁面上，找到**建立新 API** 區段，並確認已選取**新 API**。

1. 設定下列欄位：
   + API 名稱：**opensearch-api**
   + 描述：**搜尋 Amazon OpenSearch Service 網域的公有 API**
   + 端點類型：**區域**

1. 選擇**建立 API**。

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

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

1. 進行下列設定，然後選擇 **Save** (儲存)：


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

### 設定方法請求
<a name="method-request"></a>

選擇 **Method Request** (方法請求)，然後進行下列設定：


| 設定 | Value | 
| --- | --- | 
| Authorization | NONE | 
| 請求驗證程式 |  驗證查詢字串參數與標頭   | 
| 需要 API 金鑰 | false | 

在 **URL 查詢字串參數**下，選擇**新增查詢字串**並設定下列參數：


| 設定 | Value | 
| --- | --- | 
| 名稱 | q | 
| 必要 |  是  | 

### 部署 API 並設定階段
<a name="deploy-api"></a>

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

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

1. 對於 **Deployment stage** (部署階段)，選擇 **New Stage** (新增階段) 並將階段命名為 `opensearch-api-test`。

1. 選擇**部署**。

1. 在階段編輯器中進行下列設定，然後選擇 **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](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-create-api.html) 和[在 Amazon API Gateway 中部署 REST API](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-deploy-api.html)。

## 步驟 4：(選用) 修改網域存取政策
<a name="search-example-perms"></a>

OpenSearch Service 網域必須允許 ​Lambda 函數對 `movies` 索引進行 ​`GET` 請求。如果您的網域具有啟用了精細存取控制的開放存取政策，可以保持原樣：

------
#### [ 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 自動建立之角色的確切名稱，請前往 AWS 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 Dashboards 中[將角色映射至使用者](fgac.md#fgac-mapping)，否則您將看到許可錯誤。

### 設定 Lambda 執行角色許可
<a name="search-example-lambda-iam"></a>

除了設定網域存取政策之外，您還必須確保 Lambda 執行角色具有存取 OpenSearch Service 網域所需的 IAM 許可。Lambda 函數需要特定許可，取決於您使用的是受管網域或 OpenSearch Service Serverless 集合。

**對於受管 OpenSearch Service 網域：**

將下列 IAM 政策連接至您的 Lambda 執行角色，以允許其向 OpenSearch Service 網域提出請求：

------
#### [ 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 Service Serverless 集合：**

如果您使用的是 OpenSearch Service Serverless，請將下列 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. 導覽至 IAM 主控台，網址為 [https://console.aws.amazon.com/iam/](https://console.aws.amazon.com/iam/)。

1. 選擇**角色**並搜尋您的 Lambda 執行角色 （通常名為 `opensearch-lambda-role-xxxxxxxx`)。

1. 選擇**新增許可**，然後選擇**建立內嵌政策**。

1. 選擇 **JSON** 索引標籤，然後從上方貼上適當的政策，將預留位置值取代為實際的資源 ARNs。

1. 選擇**檢閱政策**，提供類似 的名稱`OpenSearchAccess`，然後選擇**建立政策**。

**注意**  
如果沒有這些 IAM 許可，即使網域存取政策允許請求，您的 Lambda 函數也會在嘗試查詢 OpenSearch Service 網域時收到「存取遭拒」錯誤。

如需存取政策的詳細資訊，請參閱[設定存取政策](createupdatedomains.md#createdomain-configure-access-policies)。

## 映射 Lambda 角色 (如果使用精細存取控制)
<a name="search-example-perms-fgac"></a>

精細存取控制會在您可以測試應用程式之前引進額外的步驟。即使您將 HTTP 基本身分驗證用於所有其他目的，您也需要將 Lambda 角色映射至使用者，否則您會看到許可錯誤。

1. 導覽至網域的 OpenSearch Dashboards URL。

1. 從主功能表中，選擇**安全性**、**角色**，然後選取 的連結`all_access`，這是您需要映射 Lambda 角色的角色。

1. 選擇 **Mapped users** (已映射的使用者)、**Manage mapping** (管理映射)。

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

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

## 步驟 5：測試 Web 應用程式
<a name="search-example-webpage"></a>

**若要測試 web 應用程式**

1. 下載 [sample-site.zip](samples/sample-site.zip)，將其解壓縮並使用您最愛的文字編輯器將 `scripts/search.js`​ 開啟。

1. 更新 `apigatewayendpoint`變數以指向您的 API Gateway 端點，並將反斜線新增至指定路徑的結尾。您可以透過選擇 **Stages** (階段)，然後選取 API 的名稱，在 API Gateway 中快速找到端點。`apigatewayendpoint` 變數應該採用 `https://some-id.execute-api.us-west-1.amazonaws.com/opensearch-api-test`/ 的形式。

1. 開啟 `index.html` 並嘗試對 *thor*、*house*​ 和一些其他術語執行搜尋。  
![\[對 thor 進行範例搜尋。\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/search-ui.png)

### 對 CORS 錯誤進行疑難排解
<a name="search-example-cors"></a>

即使 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](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors-console.html)。在 **Advanced** (進階) 下，將 **Access-Control-Allow-Credentials** 設定為 `'true'`。

1. 在 API Gateway 中重新部署 API (**Actions** (動作)、**Deploy API** (部署 API))。

1. 刪除並重新新增您的 Lambda 函數觸發程序。新增重新新增，選擇**新增觸發**並建立叫用函數的 HTTP 端點。觸發必須具有以下組態：    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/search-example.html)

## 後續步驟
<a name="search-example-next"></a>

本章只是展縣概念的起點。您可以考慮以下修改：
+ 將自己的資料新增到 OpenSearch Service 網域。
+ 將方法新增至 API
+ 在 Lambda​ 函數中，修改搜尋查詢或提升不同的欄位。
+ 樣式結果不同或修改 `search.js`​ 來向使用者顯示不同的欄位。

# 教學課程：使用 OpenSearch Service 和 OpenSearch Dashboards，將客戶支援呼叫視覺化
<a name="walkthrough"></a>

此章節是一個完整的逐步解說，情況如下：業務收到不少客戶支援呼叫，想要對其進行分析。每個呼叫的主題為何？ 有多少是正面的？ 有多少是負面的？ 主管人員如何搜尋或檢閱這些呼叫的文字記錄？

手動工作流程可能涉及員工聆聽錄音、記下每個呼叫的主題，以及判斷客戶互動是否正面。

這類的程序是非常費工的。假設每個呼叫平均時間為 10 分鐘，那麼每個員工每天只能聆聽 48 個呼叫。排除人的偏見後，所產生的資料使有極高的準確度，而*資料量*會降到最低：只需呼叫的主題，以及有關客戶是否滿意的布林值。若再加上更多資料如完整的文字記錄，便需要花大量時間。

使用 [Amazon S3](https://aws.amazon.com/s3/)、[Amazon Transcribe](https://aws.amazon.com/transcribe/)、[Amazon Comprehend](https://aws.amazon.com/comprehend/) 和 Amazon OpenSearch Service，便能以極少的程式碼自動化類似的程序，所產生的資料量非常多。例如，您可以取得呼叫的完整文字記錄、文字記錄的關鍵字和呼叫的整體「情緒」(正面、負面、中立或混合)。然後，您可以使用 OpenSearch 和 OpenSearch Dashboards 來搜尋和視覺化資料。

您可以一字不漏地遵照此逐步解說來執行，用意只是為了讓您在 OpenSearch Service 中編製索引之前，激盪出有關如何使 JSON 文件更加豐富的想法。

**評估成本**

一般而言，執行這個逐步解說中的步驟的成本不到 2 美元。此逐步解說使用下列資源：
+ S3 儲存貯體的傳輸和儲存量少於 100 MB

  如需進一步了解，請參閱 [Amazon S3 定價](https://aws.amazon.com/s3/pricing/)。
+ 具有一個 `t2.medium` 執行個體和 10 GiB 的 EBS 儲存空間，運作長達數小時的 OpenSearch Service 網域

  如需進一步了解，請參閱 [Amazon OpenSearch Service 定價](https://aws.amazon.com/elasticsearch-service/pricing/)。
+ 對 Amazon Transcribe 的數個呼叫

  如需進一步了解，請參閱 [Amazon Transcribe 定價](https://aws.amazon.com/transcribe/pricing/)。
+ 對 Amazon Comprehend 的數個自然語言處理呼叫

  如需進一步了解，請參閱 [Amazon Comprehend 定價](https://aws.amazon.com/comprehend/pricing/)。

**Topics**
+ [步驟 1：設定先決條件](#walkthrough-prereq)
+ [步驟 2：複製範本程式碼](#walkthrough-script)
+ [(選用) 步驟 3：索引範例資料](#walkthrough-sample-data)
+ [步驟 4：分析和視覺化您的資料](#walkthrough-analysis)
+ [步驟 5：清除資源和後續步驟](#walkthrough-next-steps)

## 步驟 1：設定先決條件
<a name="walkthrough-prereq"></a>

繼續之前，您必須準備好以下資源。


****  

| 先決條件 | Description | 
| --- | --- | 
| Amazon S3 儲存貯體 | 如需詳細資訊，請參閱 Amazon Simple Storage Service 主控台使用者指南中的[建立儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/userguide/CreatingABucket.html)。 | 
| OpenSearch Service 網域 | 資料的目的地。如需詳細資訊，請參閱[建立 OpenSearch Service 網域](createupdatedomains.md#createdomains)。 | 

如果尚未擁有這些資源，您可以使用下列 AWS CLI 命令建立資源：

```
aws s3 mb s3://my-transcribe-test --region us-west-2
```

```
aws opensearch create-domain --domain-name my-transcribe-test --engine-version OpenSearch_1.0 --cluster-config  InstanceType=t2.medium.search,InstanceCount=1 --ebs-options EBSEnabled=true,VolumeType=standard,VolumeSize=10 --access-policies '{"Version": "2012-10-17",		 	 	 "Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::123456789012:root"},"Action":"es:*","Resource":"arn:aws:es:us-west-2:123456789012:domain/my-transcribe-test/*"}]}' --region us-west-2
```

**注意**  
這些命令使用 `us-west-2` 區域，但您可以使用 Amazon Comprehend 支援的任何區域。如需進一步了解，請參閱[AWS 一般參考](https://docs.aws.amazon.com/general/latest/gr/rande.html#comprehend_region)。

## 步驟 2：複製範本程式碼
<a name="walkthrough-script"></a>

1. 複製下列 Python 3 範本程式碼，並貼上到名為 `call-center.py` 的新檔案：

   ```
   import boto3
   import datetime
   import json
   import requests
   from requests_aws4auth import AWS4Auth
   import time
   import urllib.request
   
   # Variables to update
   audio_file_name = '' # For example, 000001.mp3
   bucket_name = '' # For example, my-transcribe-test
   domain = '' # For example, https://search-my-transcribe-test-12345.us-west-2.es.amazonaws.com
   index = 'support-calls'
   type = '_doc'
   region = 'us-west-2'
   
   # Upload audio file to S3.
   s3_client = boto3.client('s3')
   
   audio_file = open(audio_file_name, 'rb')
   
   print('Uploading ' + audio_file_name + '...')
   response = s3_client.put_object(
       Body=audio_file,
       Bucket=bucket_name,
       Key=audio_file_name
   )
   
   # # Build the URL to the audio file on S3.
   # # Only for the us-east-1 region.
   # mp3_uri = 'https://' + bucket_name + '.s3.amazonaws.com/' + audio_file_name
   
   # Get the necessary details and build the URL to the audio file on S3.
   # For all other regions.
   response = s3_client.get_bucket_location(
       Bucket=bucket_name
   )
   bucket_region = response['LocationConstraint']
   mp3_uri = 'https://' + bucket_name + '.s3-' + bucket_region + '.amazonaws.com/' + audio_file_name
   
   # Start transcription job.
   transcribe_client = boto3.client('transcribe')
   
   print('Starting transcription job...')
   response = transcribe_client.start_transcription_job(
       TranscriptionJobName=audio_file_name,
       LanguageCode='en-US',
       MediaFormat='mp3',
       Media={
           'MediaFileUri': mp3_uri
       },
       Settings={
           'ShowSpeakerLabels': True,
           'MaxSpeakerLabels': 2 # assumes two people on a phone call
       }
   )
   
   # Wait for the transcription job to finish.
   print('Waiting for job to complete...')
   while True:
       response = transcribe_client.get_transcription_job(TranscriptionJobName=audio_file_name)
       if response['TranscriptionJob']['TranscriptionJobStatus'] in ['COMPLETED', 'FAILED']:
           break
       else:
           print('Still waiting...')
       time.sleep(10)
   
   transcript_uri = response['TranscriptionJob']['Transcript']['TranscriptFileUri']
   
   # Open the JSON file, read it, and get the transcript.
   response = urllib.request.urlopen(transcript_uri)
   raw_json = response.read()
   loaded_json = json.loads(raw_json)
   transcript = loaded_json['results']['transcripts'][0]['transcript']
   
   # Send transcript to Comprehend for key phrases and sentiment.
   comprehend_client = boto3.client('comprehend')
   
   # If necessary, trim the transcript.
   # If the transcript is more than 5 KB, the Comprehend calls fail.
   if len(transcript) > 5000:
       trimmed_transcript = transcript[:5000]
   else:
       trimmed_transcript = transcript
   
   print('Detecting key phrases...')
   response = comprehend_client.detect_key_phrases(
       Text=trimmed_transcript,
       LanguageCode='en'
   )
   
   keywords = []
   for keyword in response['KeyPhrases']:
       keywords.append(keyword['Text'])
   
   print('Detecting sentiment...')
   response = comprehend_client.detect_sentiment(
       Text=trimmed_transcript,
       LanguageCode='en'
   )
   
   sentiment = response['Sentiment']
   
   # Build the Amazon OpenSearch Service URL.
   id = audio_file_name.strip('.mp3')
   url = domain + '/' + index + '/' + type + '/' + id
   
   # Create the JSON document.
   json_document = {'transcript': transcript, 'keywords': keywords, 'sentiment': sentiment, 'timestamp': datetime.datetime.now().isoformat()}
   
   # Provide all details necessary to sign the indexing request.
   credentials = boto3.Session().get_credentials()
   awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, 'opensearchservice', session_token=credentials.token)
   
   # Index the document.
   print('Indexing document...')
   response = requests.put(url, auth=awsauth, json=json_document, headers=headers)
   
   print(response)
   print(response.json())
   ```

1. 更新初始六個變數。

1. 使用以下命令安裝所需套件：

   ```
   pip install boto3
   pip install requests
   pip install requests_aws4auth
   ```

1. 將 MP3 放置在和 `call-center.py` 相同的目錄，並執行指令碼。範例輸出如下：

   ```
   $ python call-center.py
   Uploading 000001.mp3...
   Starting transcription job...
   Waiting for job to complete...
   Still waiting...
   Still waiting...
   Still waiting...
   Still waiting...
   Still waiting...
   Still waiting...
   Still waiting...
   Detecting key phrases...
   Detecting sentiment...
   Indexing document...
   <Response [201]>
   {u'_type': u'call', u'_seq_no': 0, u'_shards': {u'successful': 1, u'failed': 0, u'total': 2}, u'_index': u'support-calls4', u'_version': 1, u'_primary_term': 1, u'result': u'created', u'_id': u'000001'}
   ```

`call-center.py` 執行一些操作：

1. 指令碼上傳音訊檔案 (此案例為，MP3，但 Amazon Transcribe 支援數種格式) 到您的 S3 儲存貯體。

1. 它會將音訊檔案的 URL 傳送到 Amazon Transcribe，並等待文字記錄任務完成。

   完成文字記錄工作的時間取決於音訊檔案長度。採用分鐘數，而非秒數。
**提示**  
為了改善文字記錄的品質，您可以設定 Amazon Transcribe 適用的[自訂詞彙](https://docs.aws.amazon.com/transcribe/latest/dg/API_CreateVocabulary.html)。

1. 文字記錄任務完成後，指令碼會擷取文字，裁剪到 5,000 個字元，然後將其傳送至 Amazon Comprehend 進行關鍵字和情感分析。

1. 最後，指令碼會新增完整的文字記錄、關鍵字、情感及目前時間戳記至 JSON 文件，並在 OpenSearch Service 中編製索引。

**提示**  
[LibriVox ](https://librivox.org/) 已有公有網域有聲書可進行測試。

## (選用) 步驟 3：索引範例資料
<a name="walkthrough-sample-data"></a>

如果您手邊沒有大量呼叫記錄 (誰有呢)？您可以在 [sample-calls.zip](samples/sample-calls.zip) 中為範例文件[編製索引](indexing.md)，這與 `call-center.py` 所產生的結果相當。

1. 建立名為 `bulk-helper.py` 的檔案：

   ```
   import boto3
   from opensearchpy import OpenSearch, RequestsHttpConnection
   import json
   from requests_aws4auth import AWS4Auth
   
   host = '' # For example, my-test-domain.us-west-2.es.amazonaws.com
   region = '' # For example, us-west-2
   service = 'es'
   
   bulk_file = open('sample-calls.bulk', 'r').read()
   
   credentials = boto3.Session().get_credentials()
   awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token)
   
   search = OpenSearch(
       hosts = [{'host': host, 'port': 443}],
       http_auth = awsauth,
       use_ssl = True,
       verify_certs = True,
       connection_class = RequestsHttpConnection
   )
   
   response = search.bulk(bulk_file)
   print(json.dumps(response, indent=2, sort_keys=True))
   ```

1. 更新 `host` 和 `region` 兩個初始變數。

1. 使用以下命令安裝所需套件：

   ```
   pip install opensearch-py
   ```

1. 下載並解壓縮 [sample-calls.zip](samples/sample-calls.zip)。

1. 將 `sample-calls.bulk` 放置在和 `bulk-helper.py` 相同的目錄，並執行協助程式。範例輸出如下：

   ```
   $ python bulk-helper.py
   {
     "errors": false,
     "items": [
       {
         "index": {
           "_id": "1",
           "_index": "support-calls",
           "_primary_term": 1,
           "_seq_no": 42,
           "_shards": {
             "failed": 0,
             "successful": 1,
             "total": 2
           },
           "_type": "_doc",
           "_version": 9,
           "result": "updated",
           "status": 200
         }
       },
       ...
     ],
     "took": 27
   }
   ```

## 步驟 4：分析和視覺化您的資料
<a name="walkthrough-analysis"></a>

既然您在 OpenSearch Service 中有一些資料，您可以使用 OpenSearch Dashboards 將資料視覺化。

1. 導覽至 `https://search-domain.region.es.amazonaws.com/_dashboards`。

1. 在使用 OpenSearch Dashboards 之前，您需要索引模式。Dashboards 使用索引模式將分析縮小至一個或多個索引。若要匹配 `call-center.py` 建立的 `support-calls` 索引，請前往 **Stack Management** (堆疊管理)、**Index Patterns** (索引模式)，並定義 `support*` 的索引模式，然後選擇 **Next step** (下一個步驟)。

1. 對於 **Time Filter field name (時間篩選條件欄位名稱)**，請選擇 **timestamp (時間戳記)**。

1. 您現在可以開始建立視覺化效果。選擇 **Visualize (視覺化)**，然後新增視覺化。

1. 選擇圓餅圖和 `support*` 索引模式。

1. 預設視覺化是基本的，因此選擇 **Split Slices (分割切片)** 來建立更有趣的視覺化效果。

   對於 **Aggregation (集合)** 選項，請選擇 **Terms (條款)**。對於 **Field (欄位)**，選擇 **sentiment.keyword**。然後選擇 **Apply changes (套用變更)** 和 **Save (儲存)**。  
![\[Dashboards 圓餅圖的範例組態\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/sentiment-pie-chart.png)

1. 返回 **Visualize (視覺化)** 頁面，並新增另一個視覺化。這時，選擇水平長條圖。

1. 選擇 **Split Series (分割系列)**。

   對於 **Aggregation (集合)** 選項，請選擇 **Terms (條款)**。對於 **Field (欄位)**，選擇 **keywords.keyword**，並將 **Size (大小)** 變更為 20。然後選擇 **Apply Changes (套用變更)** 和 **Save (儲存)**。  
![\[Dashboards 水平長條圖的範例組態\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/keyword-bar-chart.png)

1. 返回 **Visualize (視覺化)** 頁面，並新增一個最終視覺化垂直長條圖。

1. 選擇 **Split Series (分割系列)**。對於 **Aggregation (彙總)**，選擇 **Date Histogram (日期分佈圖)**。對於 **Field (欄位)**，選擇 **timestamp (時間戳記)**，將 **Interval (間隔)** 變更為 **Daily (每日)**。

1. 選擇 **Metrics & Axes (指標和軸)**，並將變更 **Mode (模式)** 變更為 **normal (正常)**。

1. 選擇 **Apply Changes (套用變更)** 和 **Save (儲存)**。  
![\[Dashboards 垂直長條圖的範例組態。\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/timestamp-bar-chart-2.png)

1. 既然您有三個視覺效果，您可以將它們新增到 Dashboards 視覺效果。選擇 **Dashboard (儀表板)**、建立儀表板，並新增視覺化效果。  
![\[範例 Dashboards 視覺效果。\]](http://docs.aws.amazon.com/zh_tw/opensearch-service/latest/developerguide/images/dashboard-2.png)

## 步驟 5：清除資源和後續步驟
<a name="walkthrough-next-steps"></a>

為避免不必要的費用，請刪除 S3 儲存貯體和 OpenSearch Service 網域。如需進一步了解，請參閱 *Amazon Simple Storage Service 使用者指南*中的[刪除儲存貯體](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-or-empty-bucket.html#delete-bucket)以及本指南中的[刪除 OpenSearch Service 網域](gsgdeleting.md)。

文字記錄需要比 MP3 檔更少的磁碟空間。您也許可以縮短您的 MP3 保留時段 (例如，從三個月的呼叫記錄到一個月)，保留數年文字記錄，並且仍能節省儲存成本。

您也可以使用 AWS Step Functions 和 Lambda 自動化轉錄程序、在編製索引之前新增其他中繼資料，或製作更複雜的視覺化效果，以符合您的確切使用案例。