

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

# 使用 Lambda 處理 Amazon DocumentDB 事件
<a name="with-documentdb"></a>

您可以透過將 Amazon DocumentDB 叢集設定為事件來源，使用 Lambda 函數處理 [Amazon DocumentDB (with MongoDB compatibility) 變更串流](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html)中的事件。接著，您可以在每次使用 Amazon DocumentDB 叢集變更資料時，調用 Lambda 函數來自動執行事件驅動的工作負載。

**注意**  
Lambda 僅支援 Amazon DocumentDB 4.0 和 5.0 版。Lambda 不支援 3.6 版。  
此外，針對事件來源映射，Lambda 僅支援執行個體型叢集和區域叢集。Lambda 不支援 [彈性叢集](https://docs.aws.amazon.com/documentdb/latest/developerguide/docdb-using-elastic-clusters.html) 或 [全域叢集](https://docs.aws.amazon.com/documentdb/latest/developerguide/global-clusters.html)。使用 Lambda 做為用戶端連線至 Amazon DocumentDB 時不適用此限制。Lambda 可以連線至所有叢集類型來執行 CRUD 操作。

Lambda 會依照抵達的順序處理來自 Amazon DocumentDB 變更串流的事件。因此，函數一次只能處理來自 Amazon DocumentDB 的一個並行調用。若要監控函數，您可以追蹤其[並行指標](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-concurrency.html)。

**警告**  
Lambda 事件來源映射至少會處理每個事件一次，而且可能會重複處理記錄。為避免與重複事件相關的潛在問題，強烈建議您讓函數程式碼具有等冪性。若要進一步了解，請參閱 AWS 知識中心中的[如何使 Lambda 函數具有等冪性](https://repost.aws/knowledge-center/lambda-function-idempotent)。

**Topics**
+ [Amazon DocumentDB 事件範例](#docdb-sample-event)
+ [先決條件和許可](#docdb-prereqs)
+ [設定網路安全](#docdb-network)
+ [建立 Amazon DocumentDB 事件來源映射 (主控台)](#docdb-configuration)
+ [建立 Amazon DocumentDB 事件來源映射 (SDK 或 CLI)](#docdb-api)
+ [輪詢和串流開始位置](#docdb-stream-polling)
+ [監控 Amazon DocumentDB 事件來源](#docdb-monitoring)
+ [教學課程： AWS Lambda 搭配 Amazon DocumentDB Streams 使用](with-documentdb-tutorial.md)

## Amazon DocumentDB 事件範例
<a name="docdb-sample-event"></a>

```
{
    "eventSourceArn": "arn:aws:rds:us-east-1:123456789012:cluster:canaryclusterb2a659a2-qo5tcmqkcl03",
    "events": [
        {
            "event": {
                "_id": {
                    "_data": "0163eeb6e7000000090100000009000041e1"
                },
                "clusterTime": {
                    "$timestamp": {
                        "t": 1676588775,
                        "i": 9
                    }
                },
                "documentKey": {
                    "_id": {
                        "$oid": "63eeb6e7d418cd98afb1c1d7"
                    }
                },
                "fullDocument": {
                    "_id": {
                        "$oid": "63eeb6e7d418cd98afb1c1d7"
                    },
                    "anyField": "sampleValue"
                },
                "ns": {
                    "db": "test_database",
                    "coll": "test_collection"
                },
                "operationType": "insert"
            }
        }
    ],
    "eventSource": "aws:docdb"
}
```

如需有關此範例中事件及其形狀的詳細資訊，請參閱 MongoDB 文件網站上的[變更事件](https://www.mongodb.com/docs/manual/reference/change-events/)。

## 先決條件和許可
<a name="docdb-prereqs"></a>

將 Amazon DocumentDB 作為 Lambda 函數的事件來源使用前，請留意以下先決條件。您必須：
+ **在與函數相同的 AWS 帳戶 和 中擁有現有的 Amazon DocumentDB AWS 區域 叢集。**如果您沒有現有叢集，則可以按照*《Amazon DocumentDB 開發人員指南》*中[開始使用 Amazon DocumentDB](https://docs.aws.amazon.com/documentdb/latest/developerguide/get-started-guide.html)所述步驟建立叢集。或者，[教學課程： AWS Lambda 搭配 Amazon DocumentDB Streams 使用](with-documentdb-tutorial.md) 中的第一組步驟會引導您建立包含所有必要先決條件的 Amazon DocumentDB 叢集。
+ **允許 Lambda 存取與您 Amazon DocumentDB 叢集相關聯的 Amazon Virtual Private Cloud (Amazon VPC) 資源。**如需詳細資訊，請參閱[設定網路安全](#docdb-network)。
+ **在您的 Amazon DocumentDB 叢集上啟用 TLS。**這是預設設定。若停用 TLS，Lambda 將無法與您的叢集進行通訊。
+ **啟用 Amazon DocumentDB 叢集上的變更串流。**如需詳細資訊，請參閱*《Amazon DocumentDB 開發人員指南》*中的[透過 Amazon DocumentDB 使用變更串流](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html) 。
+ **為 Lambda 提供憑證以存取您的 Amazon DocumentDB 叢集。**設定事件來源時，請提供包含存取叢集所需驗證詳細資料 (使用者名稱和密碼) 的 [AWS Secrets Manager](https://docs.aws.amazon.com/secretsmanager/latest/userguide/intro.html) 金鑰。若要在設定期間提供此金鑰，請執行下列其中一項操作：
  + 如果您要使用 Lambda 主控台進行設定，請在 **Secrets Manager 金鑰**欄位中提供此金鑰。
  + 如果您使用 AWS Command Line Interface (AWS CLI) 進行設定，請在 `source-access-configurations`選項中提供此金鑰。您可以連同 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html) 或 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) 命令包括此選項。例如：

    ```
    aws lambda create-event-source-mapping \
        ...
        --source-access-configurations  '[{"Type":"BASIC_AUTH","URI":"arn:aws:secretsmanager:us-west-2:123456789012:secret:DocDBSecret-AbC4E6"}]' \
        ...
    ```
+ **您必須向 Lambda 授與許可，才能管理與 Amazon DocumentDB 串流相關的資源。**將下列許可手動新增到函數的 [執行角色](lambda-intro-execution-role.md)：
  + [rds:DescribeDBClusters](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusters.html)
  + [rds:DescribeDBClusterParameters](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBClusterParameters.html)
  + [rds:DescribeDBSubnetGroups](https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_DescribeDBSubnetGroups.html)
  + [ec2:CreateNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateNetworkInterface.html)
  + [ec2:DescribeNetworkInterfaces](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeNetworkInterfaces.html)
  + [ec2:DescribeVpcs](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html)
  + [ec2:DeleteNetworkInterface](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteNetworkInterface.html)
  + [ec2:DescribeSubnets](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html)
  + [ec2:DescribeSecurityGroups](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSecurityGroups.html)
  + [kms:Decrypt](https://docs.aws.amazon.com/kms/latest/APIReference/API_Decrypt.html)
  + [secretsmanager:GetSecretValue](https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html)
+ **傳送至 Lambda 的 Amazon DocumentDB 變更串流事件大小請勿超過 6 MB。**Lambda 支援的承載大小上限為 6MB。如果變更串流嘗試向 Lambda 傳送大於 6MB 的事件，Lambda 會捨棄訊息並發出 `OversizedRecordCount` 指標。Lambda 會盡力發送所有指標。

**注意**  
雖然 Lambda 函數的逾時上限通常為 15 分鐘，但 Amazon MSK、自我管理的 Apache Kafka、Amazon DocumentDB 以及 Amazon MQ for ActiveMQ 和 Amazon MQ for RabbitMQ 的事件來源映射只支援 14 分鐘逾時限制上限的函數。此限制條件可確保事件來源映射能夠正確處理函數錯誤和重試。

## 設定網路安全
<a name="docdb-network"></a>

若要透過事件來源映射授予 Lambda 對 Amazon DocumentDB 的完整存取權，您的叢集必須使用公有端點 (公有 IP 位址)，或者您必須提供建立叢集之 Amazon VPC 的存取權。

當您將 Amazon DocumentDB 與 Lambda 搭配使用時，請建立 [AWS PrivateLink VPC 端點](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html)，為您的函數提供 Amazon VPC 中資源的存取權。

**注意**  
AWS PrivateLink 具有使用事件輪詢器預設 （隨需） 模式之事件來源映射的函數需要 VPC 端點。如果您的事件來源映射使用[佈建模式](invocation-eventsourcemapping.md#invocation-eventsourcemapping-provisioned-mode)，則不需要設定 AWS PrivateLink VPC 端點。

建立端點以提供對下列資源的存取權：
+  Lambda：為 Lambda 服務主體建立端點。
+  AWS STS — 為 建立端點， AWS STS 以便服務主體代表您擔任角色。
+  Secrets Manager：如果您的叢集使用 Secrets Manager 來儲存憑證，則請為 Secrets Manager 建立端點。

或者，在 Amazon VPC 中的每個公有子網路上設定一個 NAT 閘道。如需詳細資訊，請參閱[啟用 VPC 連線的 Lambda 函數的網際網路存取](configuration-vpc-internet.md)。

當您為 Amazon DocumentDB 建立事件來源映射時，Lambda 會檢查是否已存在彈性網絡介面 (ENI)，適用於為您的 Amazon VPC 設定的子網路和安全群組。如果 Lambda 找到現有的 ENI，它會嘗試重複使用它們。否則，Lambda 會建立新的 ENI 以連線至事件來源並調用您的函數。

**注意**  
Lambda 函數一律會在 Lambda 服務所擁有的 VPC 內執行。函數的 VPC 組態不會影響事件來源映射。只有事件來源的聯網組態會決定 Lambda 如何連線至您的事件來源。

為包含叢集的 Amazon VPC 設定安全群組。依預設，Amazon DocumentDB 會使用下列連接埠：`27017`。
+ 傳入規則：允許與事件來源相關聯之安全群組的預設代理程式連接埠上的所有流量。或者，您可使用自我參照安全群組規則，允許來自同一安全群組內其他執行個體的存取。
+ 傳出規則 – 如果您的函數需要與服務通訊`443`，允許外部目的地連接埠上的所有流量 AWS 。或者，如果您不需要與其他 AWS 服務通訊，您也可以使用自我參考安全群組規則來限制對代理程式的存取。
+ Amazon VPC 端點傳入規則：如果您使用的是 Amazon VPC 端點，與您的 Amazon VPC 端點相關聯的安全群組必須允許來自叢集安全群組的連接埠 `443` 上的傳入流量。

如果您的叢集使用身分驗證，則您也可以限制 Secrets Manager 端點的端點政策。若要呼叫 Secrets Manager API，Lambda 會使用您的函數角色，而不是 Lambda 服務主體。

**Example VPC 端點政策 — Secrets Manager 端點**  

```
{
      "Statement": [
          {
              "Action": "secretsmanager:GetSecretValue",
              "Effect": "Allow",
              "Principal": {
                  "AWS": [
                      "arn:aws::iam::123456789012:role/my-role"
                  ]
              },
              "Resource": "arn:aws::secretsmanager:us-west-2:123456789012:secret:my-secret"
          }
      ]
  }
```

當您使用 Amazon VPC 端點時， 會使用端點的彈性網路界面 (ENI) AWS 路由您的 API 呼叫來叫用函數。Lambda 服務主體需要在使用這些 ENI 的任何角色和函數上呼叫 `lambda:InvokeFunction`。

根據預設，Amazon VPC 端點具有開放的 IAM 政策，允許廣泛存取資源。最佳實務是限制這些政策，以使用該端點執行所需的動作。為了確保事件來源映射能夠調用 Lambda 函數，VPC 端點政策必須允許 Lambda 服務主體呼叫 `sts:AssumeRole` 和 `lambda:InvokeFunction`。限制您的 VPC 端點政策以僅允許源自您組織內部的 API 呼叫，可阻止事件來源映射正常運作，因此在這些政策中需要 `"Resource": "*"`。

下列範例 VPC 端點政策展示了如何授予 Lambda 服務主體對 AWS STS 和 Lambda 端點的必要存取權。

**Example VPC 端點政策 — AWS STS 端點**  

```
{
      "Statement": [
          {
              "Action": "sts:AssumeRole",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
    }
```

**Example VPC 端點政策 – Lambda 端點**  

```
{
      "Statement": [
          {
              "Action": "lambda:InvokeFunction",
              "Effect": "Allow",
              "Principal": {
                  "Service": [
                      "lambda.amazonaws.com"
                  ]
              },
              "Resource": "*"
          }
      ]
  }
```

## 建立 Amazon DocumentDB 事件來源映射 (主控台)
<a name="docdb-configuration"></a>

若要讓 Lambda 函數從 Amazon DocumentDB 叢集的變更串流中讀取，請建立 DocumentDB [事件來源映射](invocation-eventsourcemapping.md)。本節會說明如何透過 Lambda 主控台執行這項操作。如需 AWS SDK 和 AWS CLI 說明，請參閱 [建立 Amazon DocumentDB 事件來源映射 (SDK 或 CLI)](#docdb-api)。

**建立 Amazon DocumentDB 事件來源映射 (主控台)**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇函數的名稱。

1. 在 **函式概觀** 下，選擇 **新增觸發條件** 。

1. 在**觸發條件組態**底下的下拉式清單中，選擇 **DocumentDB**。

1. 設定需要的選項，然後選擇**新增**。

Lambda 支援以下 Amazon DocumentDB 事件來源的選項：
+ **DocumentDB 叢集**：選取 Amazon DocumentDB 叢集。
+ **啟用觸發條件**：選擇您是否要立即啟用觸發條件。若勾選此核取方塊，您的函數會在建立事件來源映射時立即開始接收來自指定 Amazon DocumentDB 變更串流的流量。建議您取消勾選此核取方塊，以便在停用狀態下建立事件來源映射來進行測試。完成建立後，您隨時可以啟動事件來源映射。
+ **資料庫名稱：** 輸入叢集內要使用的資料庫名稱。
+ (選用) **集合名稱**：輸入資料庫內要使用的集合名稱。如果您未指定集合，Lambda 會偵聽資料庫中每個集合中的所有事件。
+ **批次大小：** 設定單一批次中要擷取的訊息數目上限 (最高 10,000)。預設批次大小為 100。
+ **開始位置：** 選擇串流中要從中開始讀取記錄的位置。
  + **最新：** 僅處理已新增到串流的新記錄。Lambda 建立完事件來源後，您的函數才會開始處理記錄。這表示系統可能會捨棄部分記錄，直到您的事件來源成功建立為止。
  + **水平修剪** - 處理所有在串流中的記錄。Lambda 會透過叢集的日誌保留持續時間來決定開始讀取事件的時間點。具體來說，Lambda 會從 `current_time - log_retention_duration` 開始進行讀取。變更串流必須在此時間戳記前處於作用中狀態，Lambda 才能正確讀取所有事件。
  + **At timestamp (在時間戳記為)** - 從特定時間開始處理記錄。變更串流必須在指定時間戳記前處於作用中狀態，Lambda 才能正確讀取所有事件。
+ **身分驗證：** 選擇在叢集中存取中介裝置的身分驗證方式。
  + **BASIC\$1AUTH：** 使用基本身分驗證下，您必須提供含有憑證的 Secrets Manager 金鑰，才能存取叢集。
+ **Secrets Manager 金鑰**：選擇含有存取 Amazon DocumentDB 叢集所需身分驗證詳細資料 (使用者名稱和密碼) 的 Secrets Manager 金鑰。
+ (選用) **批次間隔**：在調用函數前收集記錄的最長時間 (秒)，上限為 300 秒。
+ (選用) **完整文件組態**：文件更新作業方面，請選擇要傳送至串流的內容。預設值為 `Default`，這表示 Amazon DocumentDB 針對每個變更串流事件僅會傳送說明所做變更的差異。如需有關此欄位的詳細資訊，請參閱 MongoDB Javadoc API 文件中的 [FullDocument](https://mongodb.github.io/mongo-java-driver/3.9/javadoc/com/mongodb/client/model/changestream/FullDocument.html#DEFAULT)。
  + **預設：** Lambda 僅會傳送說明所做變更的部分文件。
  + **UpdateLookup：** Lambda 會傳送說明變更的差異，以及整個文件的副本。

## 建立 Amazon DocumentDB 事件來源映射 (SDK 或 CLI)
<a name="docdb-api"></a>

若要使用 [AWS SDK](https://aws.amazon.com/developer/tools/) 來建立或管理 Amazon DocumentDB 事件來源映射，您可以使用下列 API 操作：
+ [CreateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_CreateEventSourceMapping.html)
+ [ListEventSourceMappings](https://docs.aws.amazon.com/lambda/latest/api/API_ListEventSourceMappings.html)
+ [GetEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_GetEventSourceMapping.html)
+ [UpdateEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateEventSourceMapping.html)
+ [DeleteEventSourceMapping](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteEventSourceMapping.html)

若要使用 建立事件來源映射 AWS CLI，請使用 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-event-source-mapping.html)命令。以下範例使用此命令，將名為 `my-function` 的函數映射至 Amazon DocumentDB 變更串流。事件來源是由 Amazon Resource Name (ARN) 指定，批次大小為 500，且開始時間為 Unix 時間的時間戳記。此命令也會指定 Lambda 用來連線至 Amazon DocumentDB 的 Secrets Manager 金鑰。此外也包括 `document-db-event-source-config` 參數，這個參數指定了要從哪個資料庫和集合讀取。

```
aws lambda create-event-source-mapping --function-name my-function \
    --event-source-arn arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy
    --batch-size 500 \
    --starting-position AT_TIMESTAMP \
    --starting-position-timestamp 1541139109 \
    --source-access-configurations '[{"Type":"BASIC_AUTH","URI":"arn:aws:secretsmanager:us-east-1:123456789012:secret:DocDBSecret-BAtjxi"}]' \
    --document-db-event-source-config '{"DatabaseName":"test_database", "CollectionName": "test_collection"}' \
```

您應該會看到類似下面的輸出：

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "BatchSize": 500,
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "MaximumBatchingWindowInSeconds": 0,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541348195.412,
    "LastProcessingResult": "No records processed",
    "State": "Creating",
    "StateTransitionReason": "User action"
}
```

完成建立後，您可以使用 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-event-source-mapping.html) 命令來更新 Amazon DocumentDB 事件來源的設定。以下命令將批次大小更新為 1,000，並將批次間格更新為 10 秒。對於此命令，您必須擁有事件來源映射的 UUID (可使用 `list-event-source-mapping` 命令或 Lambda 主控台擷取)。

```
aws lambda update-event-source-mapping --function-name my-function \
    --uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b \
    --batch-size 1000 \
    --batch-window 10
```

您應該會看到類似以下內容的輸出：

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "BatchSize": 500,
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "MaximumBatchingWindowInSeconds": 0,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541359182.919,
    "LastProcessingResult": "OK",
    "State": "Updating",
    "StateTransitionReason": "User action"
}
```

Lambda 會以非同步方式更新設定，因此處理完成之前您可能無法在輸出中看到這些變更。若要檢視事件來源映射的目前設定，請使用 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-event-source-mapping.html) 命令。

```
aws lambda get-event-source-mapping --uuid f89f8514-cdd9-4602-9e1f-01a5b77d449b
```

您應該會看到類似以下內容的輸出：

```
{
    "UUID": "2b733gdc-8ac3-cdf5-af3a-1827b3b11284",
    "DocumentDBEventSourceConfig": {
        "CollectionName": "test_collection",
        "DatabaseName": "test_database",
        "FullDocument": "Default"
    },
    "BatchSize": 1000,
    "MaximumBatchingWindowInSeconds": 10,
    "EventSourceArn": "arn:aws:rds:us-west-2:123456789012:cluster:privatecluster7de2-epzcyvu4pjoy",
    "FunctionArn": "arn:aws:lambda:us-west-2:123456789012:function:my-function",
    "LastModified": 1541359182.919,
    "LastProcessingResult": "OK",
    "State": "Enabled",
    "StateTransitionReason": "User action"
}
```

若要刪除 Amazon DocumentDB 事件來源映射，請使用 [https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/delete-event-source-mapping.html](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/delete-event-source-mapping.html) 命令。

```
aws lambda delete-event-source-mapping \
    --uuid 2b733gdc-8ac3-cdf5-af3a-1827b3b11284
```

## 輪詢和串流開始位置
<a name="docdb-stream-polling"></a>

請注意，建立和更新事件來源映射期間的串流輪詢最終會一致。
+ 在建立事件來源映射期間，從串流開始輪詢事件可能需要幾分鐘時間。
+ 在更新事件來源映射期間，從串流停止並重新開始輪詢事件可能需要幾分鐘時間。

這種行為表示如果您指定 `LATEST` 當作串流的開始位置，事件來源映射可能會在建立或更新期間遺漏事件。若要確保沒有遺漏任何事件，請將串流開始位置指定為 `TRIM_HORIZON` 或 `AT_TIMESTAMP`。

## 監控 Amazon DocumentDB 事件來源
<a name="docdb-monitoring"></a>

為協助您監控 Amazon DocumentDB 事件來源，Lambda 會在您的函數處理完一批記錄後發出 `IteratorAge` 指標。*迭代器存留期*是最近事件和目前時間戳記之間的差距。基本上，`IteratorAge` 指標會指出批次中最後處理的記錄經過了多久的時間。如果函數目前正在處理新的事件，可使用迭代器存留期來預估記錄新增與函數實際處理之間的延遲。從 `IteratorAge` 的增加趨勢可看出您函數的問題。如需詳細資訊，請參閱[將 CloudWatch 指標與 Lambda 搭配使用](monitoring-metrics.md)。

Amazon DocumentDB 變更串流未最佳化，無法處理事件之間的大量時間間隔。如果 Amazon DocumentDB 事件來源長時間未收到任何事件，Lambda 可能會停用事件來源映射。此期間長度可能從幾週到幾個月不等，取決於叢集大小和其他工作負載。

Lambda 支援的承載上限為 6MB。不過，Amazon DocumentDB 變更串流事件的大小可達 16MB。如果變更串流嘗試向 Lambda 傳送大於 6MB 的變更串流事件，Lambda 會捨棄訊息並發出 `OversizedRecordCount` 指標。Lambda 會盡力發送所有指標。

# 教學課程： AWS Lambda 搭配 Amazon DocumentDB Streams 使用
<a name="with-documentdb-tutorial"></a>

 在本教學課程中，您將建立一個基礎 Lambda 函數，它會從 Amazon DocumentDB (with MongoDB compatibility) 變更串流中取用事件。完成本教學課程需逐一進行以下階段：
+ 設定您的 Amazon DocumentDB 叢集、連線到叢集，然後在叢集上啟用變更串流。
+ 建立 Lambda 函數，並將 Amazon DocumentDB 叢集設定為函數的事件來源。
+ 將項目插入 Amazon DocumentDB 資料庫中，即可測試設定。

## 建立 Amazon DocumentDB 叢集
<a name="docdb-documentdb-cluster"></a>

1. 開啟 [Amazon DocumentDB 主控台](https://console.aws.amazon.com/docdb/home#)。在**叢集**下，選擇**建立**。

1. 使用下列組態建立叢集：
   + 在**叢集類型**欄位中，選擇**執行個體型叢集**。此為預設選項。
   + 在**叢集組態**欄位中，確保已選取**引擎版本** 5.0.0。此為預設選項。
   + 在**執行個體組態**欄位中：
     + 在**資料庫執行個體類別**欄位中，選取**記憶體最佳化類別**。此為預設選項。
     + 在**常規複本執行個體數量**欄位中，選擇 1。
     + 在**執行個體類別**欄位中，使用預設選項。
   + 在**身分驗證**欄位中，輸入主要使用者的使用者名稱，然後選擇**自我管理**。輸入密碼，然後進行確認。
   + 請保留所有其他預設設定。

1. 選擇 **Create Cluster** (建立叢集)。

## 在 Secrets Manager 中建立密碼
<a name="docdb-secret-in-secrets-manager"></a>

當 Amazon DocumentDB 正在建立叢集時，請建立 AWS Secrets Manager 秘密來存放資料庫登入資料。在後續步驟中建立 Lambda 事件來源映射時，您需要提供此秘密。

**在 Secrets Manager 中建立密碼**

1. 開啟 [Secrets Manager](https://console.aws.amazon.com/secretsmanager/home#) 主控台，並選擇**儲存新密碼**。

1. 針對**選擇密碼類型**，選擇以下選項：
   + 在**基本詳細資訊**下：
     + **密碼類型**：Amazon DocumentDB 資料庫的憑證
     + 在**憑證**欄位中，輸入用於建立 Amazon DocumentDB 叢集的相同使用者名稱與密碼。
     + **資料庫**：選擇您的 Amazon DocumentDB 叢集。
     + 選擇**下一步**。

1. 針對**設定密碼**，選擇下列選項：
   + **秘密名稱**：`DocumentDBSecret`
   + 選擇**下一步**。

1. 選擇**下一步**。

1. 選擇**儲存**。

1. 重新整理主控台以確認您已成功儲存 `DocumentDBSecret` 密碼。

請記錄**秘密 ARN**。在後續步驟中需要它。

## 連線至叢集
<a name="docdb-connect-to-cluster"></a>

**使用 連線至您的 Amazon DocumentDB 叢集 AWS CloudShell**

1. 在 Amazon DocumentDB 管理主控台的**叢集**下，找到已建立的叢集。按一下叢集旁的核取方塊，選擇對應叢集。

1. 選擇**連線至叢集**。CloudShell **執行命令**畫面隨即顯示。

1. 在**新增環境名稱**欄位中，輸入唯一名稱 (例如 "test")，然後選擇**建立並執行**。

1. 出現提示時，輸入您的密碼。當提示變為 `rs0 [direct: primary] <env-name>>`，表示已成功連線至 Amazon DocumentDB 叢集。

## 啟用變更串流
<a name="docdb-activate-change-streams"></a>

在本教學課程中，您將追蹤 Amazon DocumentDB 叢集中 `docdbdemo` 資料庫 `products` 集合的變更。可以透過啟用[變更串流](https://docs.aws.amazon.com/documentdb/latest/developerguide/change_streams.html)來完成此操作。

**在叢集內建立新資料庫**

1. 執行下列命令，建立名為 `docdbdemo` 的新資料庫：

   ```
   use docdbdemo
   ```

1. 在終端機視窗中，使用下列命令將記錄插入 `docdbdemo`：

   ```
   db.products.insertOne({"hello":"world"})
   ```

   您應該會看到如下所示的輸出：

   ```
   {
     acknowledged: true,
     insertedId: ObjectId('67f85066ca526410fd531d59')
   }
   ```

1. 接下來，使用以下命令在 `docdbdemo` 資料庫的 `products` 集合上啟用變更串流：

   ```
   db.adminCommand({modifyChangeStreams: 1,
       database: "docdbdemo",
       collection: "products", 
       enable: true});
   ```

    您應該會看到類似下面的輸出：

   ```
   { "ok" : 1, "operationTime" : Timestamp(1680126165, 1) }
   ```

## 建立介面 VPC 端點
<a name="docdb-create-interface-vpc-endpoints"></a>

接下來，建立[介面 VPC 端點](https://docs.aws.amazon.com/vpc/latest/privatelink/create-interface-endpoint.html#create-interface-endpoint-aws)，以確保 Lambda 和 Secrets Manager (稍後用來儲存我們的叢集存取憑證) 可以連線到您的預設 VPC。

**建立介面 VPC 端點**

1. 開啟 [VPC 主控台](https://console.aws.amazon.com/vpc/home#)。在左側選單的**虛擬私有雲端**下，選擇**端點**。

1. 選擇**建立端點**。使用下列組態建立端點：
   + 針對**名稱標籤**，輸入 `lambda-default-vpc`。
   + 針對**服務類別**，選擇 AWS 服務。
   + 針對**服務**，在搜尋方塊中輸入 `lambda`。選擇格式為 `com.amazonaws.<region>.lambda` 的服務。
   + 在 **VPC** 欄位中，選擇 Amazon DocumentDB 叢集所在的 VPC。這通常是[預設 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html)。
   + 針對**子網路**，請核取每個可用區域旁邊的方塊。請選擇每個可用區域的正確子網路。
   + 針對 **IP 地址類型**，請選擇 IPv4。
   + 在**安全群組**欄位中，選擇 Amazon DocumentDB 叢集所使用的安全群組。這通常是 `default` 安全群組。
   + 請保留所有其他預設設定。
   + 選擇**建立端點**。

1. 再次選擇**建立端點**。使用下列組態建立端點：
   + 針對**名稱標籤**，輸入 `secretsmanager-default-vpc`。
   + 針對**服務類別**，選擇 AWS 服務。
   + 針對**服務**，在搜尋方塊中輸入 `secretsmanager`。選擇格式為 `com.amazonaws.<region>.secretsmanager` 的服務。
   + 在 **VPC** 欄位中，選擇 Amazon DocumentDB 叢集所在的 VPC。這通常是[預設 VPC](https://docs.aws.amazon.com/vpc/latest/userguide/default-vpc.html)。
   + 針對**子網路**，請核取每個可用區域旁邊的方塊。請選擇每個可用區域的正確子網路。
   + 針對 **IP 地址類型**，請選擇 IPv4。
   + 在**安全群組**欄位中，選擇 Amazon DocumentDB 叢集所使用的安全群組。這通常是 `default` 安全群組。
   + 請保留所有其他預設設定。
   + 選擇**建立端點**。

 這就完成了本教學課程的叢集設定部分。

## 建立執行角色
<a name="docdb-create-the-execution-role"></a>

 在接下來的一組步驟中，您將建立 Lambda 函數。首先，您需要建立授予函數存取叢集許可的執行角色。您可先建立 IAM 政策，然後將此政策連接到 IAM 角色。

**建立 IAM 政策**

1. 開啟 IAM 主控台的[政策頁面](https://console.aws.amazon.com/iam/home#/policies)，並選擇**建立政策**。

1. 選擇 **JSON** 標籤。在下列政策中，將陳述式最後一行中的 Secrets Manager 資源 ARN 取代為先前的密碼 ARN，並將政策複製到編輯器中。

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

****  

   ```
   {
       "Version":"2012-10-17",		 	 	 
       "Statement": [
           {
               "Sid": "LambdaESMNetworkingAccess",
               "Effect": "Allow",
               "Action": [
                   "ec2:CreateNetworkInterface",
                   "ec2:DescribeNetworkInterfaces",
                   "ec2:DescribeVpcs",
                   "ec2:DeleteNetworkInterface",
                   "ec2:DescribeSubnets",
                   "ec2:DescribeSecurityGroups",
                   "kms:Decrypt"
               ],
               "Resource": "*"
           },
           {
               "Sid": "LambdaDocDBESMAccess",
               "Effect": "Allow",
               "Action": [
                   "rds:DescribeDBClusters",
                   "rds:DescribeDBClusterParameters",
                   "rds:DescribeDBSubnetGroups"
               ],
               "Resource": "*"
           },
           {
               "Sid": "LambdaDocDBESMGetSecretValueAccess",
               "Effect": "Allow",
               "Action": [
                   "secretsmanager:GetSecretValue"
               ],
               "Resource": "arn:aws:secretsmanager:us-east-1:123456789012:secret:DocumentDBSecret"
           }
       ]
   }
   ```

------

1. 選擇**下一步：標籤**，然後選擇**下一步：檢閱**。

1. 對於 **Name** (名稱)，輸入 `AWSDocumentDBLambdaPolicy`。

1. 選擇**建立政策**。

**建立 IAM 角色**

1. 開啟 IAM 主控台的[角色](https://console.aws.amazon.com/iam/home#/roles)頁面，然後選擇**建立角色**。

1. 針對**選取信任的實體**，請選擇以下選項：
   + **信任的實體類型**： AWS 服務
   + **服務或使用案例**：Lambda
   + 選擇**下一步**。

1. 針對**新增許可**，請選擇您剛建立的 `AWSDocumentDBLambdaPolicy` 政策以及 `AWSLambdaBasicExecutionRole`，授予函數寫入 Amazon CloudWatch Logs 的許可。

1. 選擇**下一步**。

1. 在**角色名稱**中，輸入 `AWSDocumentDBLambdaExecutionRole`。

1. 選擇建**立角色**。

## 建立 Lambda 函式
<a name="docdb-create-the-lambda-function"></a>

本教學課程使用 Python 3.14 執行時間，但我們也提供其他執行時間的範例程式碼檔案。您可以在下列方塊中選取索引標籤，查看您感興趣的執行期程式碼。

程式碼會接收 Amazon DocumentDB 事件輸入，並處理其包含的訊息。

**建立 Lambda 函數**

1. 開啟 Lambda 主控台中的[函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇**建立函數**。

1. 選擇**從頭開始撰寫**

1. 在**基本資訊**下，請執行下列動作：

   1. 在**函數名稱**輸入 `ProcessDocumentDBRecords`

   1. 針對**執行期**，選擇 **Python 3.14。**

   1. 對於 **Architecture** (架構)，選擇 **x86\$164**。

1. 在**變更預設執行角色**索引標籤中，執行下列操作：

   1. 展開索引標籤，然後選擇**使用現有角色**。

   1. 選擇您之前建立的 `AWSDocumentDBLambdaExecutionRole`。

1. 選擇**建立函數**。

**部署函數程式碼**

1. 在以下方塊中選擇 **Python** 索引標籤，然後複製程式碼。

------
#### [ .NET ]

**適用於 .NET 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 .NET 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   using Amazon.Lambda.Core;
   using System.Text.Json;
   using System;
   using System.Collections.Generic;
   using System.Text.Json.Serialization;
   //Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
   [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
   
   namespace LambdaDocDb;
   
   public class Function
   {
       
        /// <summary>
       /// Lambda function entry point to process Amazon DocumentDB events.
       /// </summary>
       /// <param name="event">The Amazon DocumentDB event.</param>
       /// <param name="context">The Lambda context object.</param>
       /// <returns>A string to indicate successful processing.</returns>
       public string FunctionHandler(Event evnt, ILambdaContext context)
       {
           
           foreach (var record in evnt.Events)
           {
               ProcessDocumentDBEvent(record, context);
           }
   
           return "OK";
       }
   
        private void ProcessDocumentDBEvent(DocumentDBEventRecord record, ILambdaContext context)
       {
           
           var eventData = record.Event;
           var operationType = eventData.OperationType;
           var databaseName = eventData.Ns.Db;
           var collectionName = eventData.Ns.Coll;
           var fullDocument = JsonSerializer.Serialize(eventData.FullDocument, new JsonSerializerOptions { WriteIndented = true });
   
           context.Logger.LogLine($"Operation type: {operationType}");
           context.Logger.LogLine($"Database: {databaseName}");
           context.Logger.LogLine($"Collection: {collectionName}");
           context.Logger.LogLine($"Full document:\n{fullDocument}");
       }
   
   
   
       public class Event
       {
           [JsonPropertyName("eventSourceArn")]
           public string EventSourceArn { get; set; }
   
           [JsonPropertyName("events")]
           public List<DocumentDBEventRecord> Events { get; set; }
   
           [JsonPropertyName("eventSource")]
           public string EventSource { get; set; }
       }
   
       public class DocumentDBEventRecord
       {
           [JsonPropertyName("event")]
           public EventData Event { get; set; }
       }
   
       public class EventData
       {
           [JsonPropertyName("_id")]
           public IdData Id { get; set; }
   
           [JsonPropertyName("clusterTime")]
           public ClusterTime ClusterTime { get; set; }
   
           [JsonPropertyName("documentKey")]
           public DocumentKey DocumentKey { get; set; }
   
           [JsonPropertyName("fullDocument")]
           public Dictionary<string, object> FullDocument { get; set; }
   
           [JsonPropertyName("ns")]
           public Namespace Ns { get; set; }
   
           [JsonPropertyName("operationType")]
           public string OperationType { get; set; }
       }
   
       public class IdData
       {
           [JsonPropertyName("_data")]
           public string Data { get; set; }
       }
   
       public class ClusterTime
       {
           [JsonPropertyName("$timestamp")]
           public Timestamp Timestamp { get; set; }
       }
   
       public class Timestamp
       {
           [JsonPropertyName("t")]
           public long T { get; set; }
   
           [JsonPropertyName("i")]
           public int I { get; set; }
       }
   
       public class DocumentKey
       {
           [JsonPropertyName("_id")]
           public Id Id { get; set; }
       }
   
       public class Id
       {
           [JsonPropertyName("$oid")]
           public string Oid { get; set; }
       }
   
       public class Namespace
       {
           [JsonPropertyName("db")]
           public string Db { get; set; }
   
           [JsonPropertyName("coll")]
           public string Coll { get; set; }
       }
   }
   ```

------
#### [ Go ]

**SDK for Go V2**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 Go 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   package main
   
   import (
   	"context"
   	"encoding/json"
   	"fmt"
   
   	"github.com/aws/aws-lambda-go/lambda"
   )
   
   type Event struct {
   	Events []Record `json:"events"`
   }
   
   type Record struct {
   	Event struct {
   		OperationType string `json:"operationType"`
   		NS            struct {
   			DB   string `json:"db"`
   			Coll string `json:"coll"`
   		} `json:"ns"`
   		FullDocument interface{} `json:"fullDocument"`
   	} `json:"event"`
   }
   
   func main() {
   	lambda.Start(handler)
   }
   
   func handler(ctx context.Context, event Event) (string, error) {
   	fmt.Println("Loading function")
   	for _, record := range event.Events {
   		logDocumentDBEvent(record)
   	}
   
   	return "OK", nil
   }
   
   func logDocumentDBEvent(record Record) {
   	fmt.Printf("Operation type: %s\n", record.Event.OperationType)
   	fmt.Printf("db: %s\n", record.Event.NS.DB)
   	fmt.Printf("collection: %s\n", record.Event.NS.Coll)
   	docBytes, _ := json.MarshalIndent(record.Event.FullDocument, "", "  ")
   	fmt.Printf("Full document: %s\n", string(docBytes))
   }
   ```

------
#### [ Java ]

**SDK for Java 2.x**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 Java 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   import java.util.List;
   import java.util.Map;
   
   import com.amazonaws.services.lambda.runtime.Context;
   import com.amazonaws.services.lambda.runtime.RequestHandler;
   
   public class Example implements RequestHandler<Map<String, Object>, String> {
   
       @SuppressWarnings("unchecked")
       @Override
       public String handleRequest(Map<String, Object> event, Context context) {
           List<Map<String, Object>> events = (List<Map<String, Object>>) event.get("events");
           for (Map<String, Object> record : events) {
               Map<String, Object> eventData = (Map<String, Object>) record.get("event");
               processEventData(eventData);
           }
   
           return "OK";
       }
   
       @SuppressWarnings("unchecked")
       private void processEventData(Map<String, Object> eventData) {
           String operationType = (String) eventData.get("operationType");
           System.out.println("operationType: %s".formatted(operationType));
   
           Map<String, Object> ns = (Map<String, Object>) eventData.get("ns");
   
           String db = (String) ns.get("db");
           System.out.println("db: %s".formatted(db));
           String coll = (String) ns.get("coll");
           System.out.println("coll: %s".formatted(coll));
   
           Map<String, Object> fullDocument = (Map<String, Object>) eventData.get("fullDocument");
           System.out.println("fullDocument: %s".formatted(fullDocument));
       }
   
   }
   ```

------
#### [ JavaScript ]

**適用於 JavaScript (v3) 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 JavaScript 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   console.log('Loading function');
   exports.handler = async (event, context) => {
       event.events.forEach(record => {
           logDocumentDBEvent(record);
       });
       return 'OK';
   };
   
   const logDocumentDBEvent = (record) => {
       console.log('Operation type: ' + record.event.operationType);
       console.log('db: ' + record.event.ns.db);
       console.log('collection: ' + record.event.ns.coll);
       console.log('Full document:', JSON.stringify(record.event.fullDocument, null, 2));
   };
   ```
使用 TypeScript 搭配 Lambda 使用 Amazon DocumentDB 事件  

   ```
   import { DocumentDBEventRecord, DocumentDBEventSubscriptionContext } from 'aws-lambda';
   
   console.log('Loading function');
   
   export const handler = async (
     event: DocumentDBEventSubscriptionContext,
     context: any
   ): Promise<string> => {
     event.events.forEach((record: DocumentDBEventRecord) => {
       logDocumentDBEvent(record);
     });
     return 'OK';
   };
   
   const logDocumentDBEvent = (record: DocumentDBEventRecord): void => {
     console.log('Operation type: ' + record.event.operationType);
     console.log('db: ' + record.event.ns.db);
     console.log('collection: ' + record.event.ns.coll);
     console.log('Full document:', JSON.stringify(record.event.fullDocument, null, 2));
   };
   ```

------
#### [ PHP ]

**適用於 PHP 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 PHP 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   <?php
   
   require __DIR__.'/vendor/autoload.php';
   
   use Bref\Context\Context;
   use Bref\Event\Handler;
   
   class DocumentDBEventHandler implements Handler
   {
       public function handle($event, Context $context): string
       {
   
           $events = $event['events'] ?? [];
           foreach ($events as $record) {
               $this->logDocumentDBEvent($record['event']);
           }
           return 'OK';
       }
   
       private function logDocumentDBEvent($event): void
       {
           // Extract information from the event record
   
           $operationType = $event['operationType'] ?? 'Unknown';
           $db = $event['ns']['db'] ?? 'Unknown';
           $collection = $event['ns']['coll'] ?? 'Unknown';
           $fullDocument = $event['fullDocument'] ?? [];
   
           // Log the event details
   
           echo "Operation type: $operationType\n";
           echo "Database: $db\n";
           echo "Collection: $collection\n";
           echo "Full document: " . json_encode($fullDocument, JSON_PRETTY_PRINT) . "\n";
       }
   }
   return new DocumentDBEventHandler();
   ```

------
#### [ Python ]

**適用於 Python 的 SDK (Boto3)**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 Python 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   import json
   
   def lambda_handler(event, context):
       for record in event.get('events', []):
           log_document_db_event(record)
       return 'OK'
   
   def log_document_db_event(record):
       event_data = record.get('event', {})
       operation_type = event_data.get('operationType', 'Unknown')
       db = event_data.get('ns', {}).get('db', 'Unknown')
       collection = event_data.get('ns', {}).get('coll', 'Unknown')
       full_document = event_data.get('fullDocument', {})
   
       print(f"Operation type: {operation_type}")
       print(f"db: {db}")
       print(f"collection: {collection}")
       print("Full document:", json.dumps(full_document, indent=2))
   ```

------
#### [ Ruby ]

**SDK for Ruby**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 Ruby 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   require 'json'
   
   def lambda_handler(event:, context:)
     event['events'].each do |record|
       log_document_db_event(record)
     end
     'OK'
   end
   
   def log_document_db_event(record)
     event_data = record['event'] || {}
     operation_type = event_data['operationType'] || 'Unknown'
     db = event_data.dig('ns', 'db') || 'Unknown'
     collection = event_data.dig('ns', 'coll') || 'Unknown'
     full_document = event_data['fullDocument'] || {}
   
     puts "Operation type: #{operation_type}"
     puts "db: #{db}"
     puts "collection: #{collection}"
     puts "Full document: #{JSON.pretty_generate(full_document)}"
   end
   ```

------
#### [ Rust ]

**適用於 Rust 的 SDK**  
 GitHub 上提供更多範例。尋找完整範例，並了解如何在[無伺服器範例](https://github.com/aws-samples/serverless-snippets/tree/main/integration-docdb-to-lambda)儲存庫中設定和執行。
使用 Rust 搭配 Lambda 使用 Amazon DocumentDB 事件。  

   ```
   use lambda_runtime::{service_fn, tracing, Error, LambdaEvent};
   use aws_lambda_events::{
       event::documentdb::{DocumentDbEvent, DocumentDbInnerEvent},
      };
   
   
   // Built with the following dependencies:
   //lambda_runtime = "0.11.1"
   //serde_json = "1.0"
   //tokio = { version = "1", features = ["macros"] }
   //tracing = { version = "0.1", features = ["log"] }
   //tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }
   //aws_lambda_events = "0.15.0"
   
   async fn function_handler(event: LambdaEvent<DocumentDbEvent>) ->Result<(), Error> {
       
       tracing::info!("Event Source ARN: {:?}", event.payload.event_source_arn);
       tracing::info!("Event Source: {:?}", event.payload.event_source);
     
       let records = &event.payload.events;
      
       if records.is_empty() {
           tracing::info!("No records found. Exiting.");
           return Ok(());
       }
   
       for record in records{
           log_document_db_event(record);
       }
   
       tracing::info!("Document db records processed");
   
       // Prepare the response
       Ok(())
   
   }
   
   fn log_document_db_event(record: &DocumentDbInnerEvent)-> Result<(), Error>{
       tracing::info!("Change Event: {:?}", record.event);
       
       Ok(())
   
   }
   
   #[tokio::main]
   async fn main() -> Result<(), Error> {
       tracing_subscriber::fmt()
       .with_max_level(tracing::Level::INFO)
       .with_target(false)
       .without_time()
       .init();
   
       let func = service_fn(function_handler);
       lambda_runtime::run(func).await?;
       Ok(())
       
   }
   ```

------

1. 在 Lambda 主控台的**程式碼來源**窗格中，將程式碼貼到程式碼編輯器中，取代 Lambda 建立的程式碼。

1. 在 **DEPLOY** 區段中，選擇**部署**以更新函數的程式碼：  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/getting-started-tutorial/deploy-console.png)

## 建立 Lambda 事件來源映射
<a name="docdb-create-the-lambda-event-source-mapping"></a>

 建立可將 Amazon DocumentDB 變更串流與 Lambda 函數建立關聯的事件來源映射。建立此事件來源映射之後， 會 AWS Lambda 立即開始輪詢串流。

**建立事件來源映射**

1. 開啟 Lambda 主控台中的[函數](https://console.aws.amazon.com/lambda/home#/functions)頁面。

1. 選擇您之前建立的 `ProcessDocumentDBRecords` 函數。

1. 選擇**組態**索引標籤，然後選擇左側功能表中的**觸發程序**。

1. 選擇 **Add trigger (新增觸發條件)**。

1. 在**觸發條件組態**下，針對來源選取 **Amazon DocumentDB**。

1. 使用下列組態建立事件來源映射：
   + **Amazon DocumentDB 叢集**：選擇您先前建立的叢集。
   + **資料庫名稱**：docdbdemo
   + **集合名稱**：產品
   + **批次大小**：1
   + **起始位置**：最新
   + **身分驗證**：BASIC\$1AUTH
   + **Secrets Manager 金鑰**：選擇 Amazon DocumentDB 叢集對應的秘密。其名稱應該類似 `rds!cluster-12345678-a6f0-52c0-b290-db4aga89274f`。
   + **批次時段**：1
   + **完整文件組態**：UpdateLookup

1. 選擇**新增**。建立事件來源映射可能需要幾分鐘的時間。

## 測試 函數
<a name="docdb-test-insert"></a>

等待事件來源映射進入**已啟用**狀態。這可能需要幾分鐘的時間。接著，透過插入、更新和刪除資料庫記錄來測試端對端設定。開始之前：

1. 在 CloudShell 環境中[重新連線至 Amazon DocumentDB 叢集](#docdb-connect-to-cluster)。

1. 執行下列命令，確保使用的是 `docdbdemo` 資料庫：

   ```
   use docdbdemo
   ```

### 插入記錄
<a name="docdb-test-insert"></a>

將記錄插入到 `docdbdemo` 資料庫的 `products` 集合中：

```
db.products.insertOne({"name":"Pencil", "price": 1.00})
```

透過[檢查 CloudWatch Logs](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)，確認函式已成功處理此事件。您應該會看到如下所示的日誌項目：

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/documentdb-insert-log.png)


### 更新記錄
<a name="docdb-test-update"></a>

使用下列命令更新剛剛插入的記錄：

```
db.products.updateOne(
    { "name": "Pencil" },
    { $set: { "price": 0.50 }}
)
```

透過[檢查 CloudWatch Logs](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)，確認函式已成功處理此事件。您應該會看到如下所示的日誌項目：

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/documentdb-update-log.png)


### 刪除記錄
<a name="docdb-test-delete"></a>

使用下列命令刪除剛剛更新的記錄：

```
db.products.deleteOne( { "name": "Pencil" } )
```

透過[檢查 CloudWatch Logs](monitoring-cloudwatchlogs-view.md#monitoring-cloudwatchlogs-console)，確認函式已成功處理此事件。您應該會看到如下所示的日誌項目：

![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/documentdb-delete-log.png)


## 疑難排解
<a name="docdb-lambda-troubleshooting"></a>

若未在函式的 CloudWatch 日誌中看到任何資料庫事件，請檢查下列項目：
+ 確認 Lambda 事件來源映射 (也稱為觸發程序) 處於**已啟用**狀態。事件來源映射的建立可能需要數分鐘時間。
+ 若事件來源映射**已啟用**，但您仍然無法在 CloudWatch 中看到資料庫事件：
  + 確認事件來源映射中的**資料庫名稱**設定為 `docdbdemo`。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/documentdb-trigger.png)
  + 檢查事件來源映射的**上次處理結果**欄位，看是否出現 "PROBLEM: Connection error. Your VPC must be able to connect to Lambda and STS, as well as Secrets Manager if authentication is required." 訊息。若看到此錯誤，確認[已建立 Lambda 與 Secrets Manager VPC 介面端點](#docdb-create-interface-vpc-endpoints)，且這些端點使用的 VPC 及子網路與 Amazon DocumentDB 叢集所使用的相同。  
![\[\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/documentdb-lastprocessingresult.png)

## 清除您的資源
<a name="docdb-cleanup"></a>

 除非您想要保留為此教學課程建立的資源，否則您現在便可刪除。透過刪除您不再使用的 AWS 資源，可為 AWS 帳戶避免不必要的費用。

**若要刪除 Lambda 函數**

1. 開啟 Lambda 主控台中的 [函數頁面](https://console.aws.amazon.com/lambda/home#/functions)。

1. 選擇您建立的函數。

1. 選擇 **Actions** (動作)、**Delete** (刪除)。

1. 在文字輸入欄位中輸入 **confirm**，然後選擇**刪除**。

**刪除執行角色**

1. 開啟 IAM 主控台中的 [角色頁面](https://console.aws.amazon.com/iam/home#/roles) 。

1. 選取您建立的執行角色。

1. 選擇**刪除**。

1. 在文字輸入欄位中輸入角色的名稱，然後選擇**刪除**。

**刪除 VPC 端點。**

1. 開啟 [VPC 主控台](https://console.aws.amazon.com/vpc/home#)。在左側選單的**虛擬私有雲端**下，選擇**端點**。

1. 選擇您建立的端點。

1. 選擇 **Actions** (動作)、**Delete VPC endpoints** (刪除 VPC 端點)。

1. 在文字輸入欄位中輸入 **delete**。

1. 選擇 **刪除**。

**刪除 Amazon DocumentDB 叢集**

1. 開啟 [Amazon DocumentDB 主控台](https://console.aws.amazon.com/docdb/home#)。

1. 選擇您為本教學課程建立的 Amazon DocumentDB 叢集，並停用刪除保護。

1. 在主**叢集**頁面中，再次選擇您的 Amazon DocumentDB 叢集。

1. 選擇 **動作**、**刪除**。

1. 針對**建立最終叢集快照**，請選取**否**。

1. 在文字輸入欄位中輸入 **delete**。

1. 選擇 **刪除**。

**在 Secrets Manager 中刪除密碼**

1. 開啟 [Secrets Manager 主控台](https://console.aws.amazon.com/secretsmanager/home#)。

1. 選擇您為此教學課程建立的密碼。

1. 選擇**動作**、**刪除機密**。

1. 選擇 **Schedule deletion** (排定刪除)。