

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# 取り込み中のドキュメントの強化
<a name="custom-document-enrichment"></a>

**注記**  
機能のサポートは、使用されているインデックスタイプと検索 API によって異なります。使用しているインデックスタイプと検索 API でこの機能がサポートされているかどうかを確認するには、[インデックスのタイプ](https://docs.aws.amazon.com/kendra/latest/dg/hiw-index-types.html)に関するページを参照してください。

ドキュメントの取り込みプロセス中に、コンテンツおよびドキュメントのメタデータフィールドまたは属性を変更できます。 Amazon Kendraの*カスタムドキュメントエンリッチメント*機能を使用すると、ドキュメントを取り込むときにドキュメント属性とコンテンツを作成、変更、または削除できます Amazon Kendra。つまり、必要に応じて、データを操作して取り込むことができます。

この機能を使用すると、ドキュメントをどのように処理し、 Amazon Kendraに取り込むかを制御できます。たとえば、ドキュメントの取り込み中に、ドキュメントメタデータ内の個人を特定できる情報をスクラブできます Amazon Kendra。

この機能を使用するもう 1 つの方法は、 で Lambda 関数を呼び出し AWS Lambda て、イメージの光学文字認識 (OCR)、テキストの翻訳、および検索や分析のためにデータを準備するためのその他のタスクを実行することです。例えば、関数を呼び出すと、画像上で OCR を実行できます。この関数は、画像のテキストを解釈し、各画像をテキスト文書として扱うことができます。郵送された顧客調査を受け取り、これらのアンケートを画像として保存する企業は、これらの画像をテキストドキュメントとして Amazon Kendraに取り込むことができます。その後、企業は Amazon Kendraで貴重な顧客調査情報を検索できます。

基本的な操作を使用してデータの最初の解析として適用し、次に、Lambda 関数を使用して、より複雑な操作をデータに適用できます。例えば、基本的な操作を使用してドキュメントメタデータフィールド 「Customer\$1ID」のすべての値を削除し、Lambda 関数を適用してドキュメント内のテキストの画像からテキストを抽出することができます。

## Custom Document Enrichment の仕組み
<a name="how-custom-document-enrichment-works"></a>

Custom Document Enrichment の全体のプロセスは次のとおりです。

1. データソースを作成または更新するとき、またはドキュメントのインデックスを直接作成するときに、カスタムドキュメントエンリッチメントを設定します Amazon Kendra。

1. Amazon Kendra はインライン設定または基本ロジックを適用してデータを変更します。詳細については、「[メタデータを変更する基本操作](#basic-data-maniplation)」を参照してください。

1. 高度なデータ操作を設定する場合は、これを元の raw ドキュメントに適用するか、構造化された解析済みドキュメントに適用 Amazon Kendra できます。詳細については、「[Lambda 関数:メタデータまたはコンテンツの抽出と変更](#advanced-data-manipulation)」を参照してください。

1. 変更されたドキュメントが取り込まれます Amazon Kendra。

このプロセスのどの時点でも、構成が有効でない場合、 Amazon Kendra はエラーをスローします。

[CreateDataSource](https://docs.aws.amazon.com/kendra/latest/APIReference/API_CreateDataSource.html)、[UpdateDataSource](https://docs.aws.amazon.com/kendra/latest/APIReference/API_UpdateDataSource.html)、または [BatchPutDocument](https://docs.aws.amazon.com/kendra/latest/APIReference/API_BatchPutDocument.html) API を呼び出す場合、Custom Document Enrichment 構成を指定します。`BatchPutDocument` を呼び出すと、各リクエストで Custom Document Enrichment を設定する必要があります。コンソールを使用する場合は、インデックスを選択し、**[Document enrichments]** (ドキュメントのエンリッチメント) をクリックして、Custom Document Enrichment を構成します。

コンソールで**[ドキュメントのエンリッチメント]** を使用する場合、API を使用する場合と同様に、基本操作のみ、Lambda 関数のみ、あるいはその両方を設定できます。コンソールステップで **[次へ]** を選択して、基本操作を設定せず、Lambda 関数のみを設定するよう選択できます。これには、元の (抽出前) データに適用するか構造化データ (抽出後) に適用するかなどが含まれます。設定を保存するには、コンソールのすべてのステップを完了する必要があります。すべての手順を完了しないと、ドキュメントの設定は保存されません。

## メタデータを変更する基本操作
<a name="basic-data-maniplation"></a>

基本ロジックを使用して、ドキュメントのフィールド、およびコンテンツを操作できます。これには、フィールド内の値の削除、条件を使用したフィールドの値の変更、またはフィールドの作成が含まれます。基本ロジックを使用して操作できる範囲を超える高度な操作については、Lambda 関数を呼び出します。詳細については、「[Lambda 関数:メタデータまたはコンテンツの抽出と変更](#advanced-data-manipulation)」を参照してください。

基本ロジックを適用するには、[DocumentAttributeTarget](https://docs.aws.amazon.com/kendra/latest/APIReference/API_DocumentAttributeTarget.html) オブジェクトを使用して操作するターゲットフィールドを指定します。属性キーを指定します。例えば、「Department」キーは、ドキュメントに関連付けられているすべての部門名を保持するフィールドまたは属性です。特定の条件が満たされた場合に、ターゲットフィールドで使用する値を指定することもできます。条件の設定は、[DocumentAttributeCondition](https://docs.aws.amazon.com/kendra/latest/APIReference/API_DocumentAttributeCondition.html) オブジェクトを使用します。例えば、「Source\$1URI」フィールドに URI 値に「financial」が含まれている場合に、ターゲットフィールド「Department」にドキュメントのターゲット値「Finance」を事前に入力するという条件を設定します。ターゲットドキュメント属性の値を削除することもできます。

コンソールを使用して基本ロジックを適用するには、インデックスを選択し、ナビゲーションメニューの **[Document enrichments]** (ドキュメントのエンリッチメント) を選択します。**[基本的な演算の設定]** をクリックして、ドキュメントのフィールドとコンテンツに基本的な演算を適用します。

次に、基本ロジックを使用して「Customer\$1ID」というドキュメントフィールドのすべての顧客識別番号を削除する例を示します。

**例 1: ドキュメントに関連付けられている顧客識別番号の削除**

基本操作が適用される前のデータ。


| **Document\$1ID** | **Body\$1Text** | **Customer\$1ID** | 
| --- | --- | --- | 
| 1 | Lorem Ipsum。 | CID1234 | 
| 2 | Lorem Ipsum。 | CID1235 | 
| 3 | Lorem Ipsum。 | CID1236 | 

基本操作が適用された後のデータ。


| **Document\$1ID** | **Body\$1Text** | **Customer\$1ID** | 
| --- | --- | --- | 
| 1 | Lorem Ipsum。 |   | 
| 2 | Lorem Ipsum。 |   | 
| 3 | Lorem Ipsum。 |   | 

次に、基本ロジックを使用して「Department」というフィールドを作成し、「source\$1URI」フィールドの情報に基づいてこのフィールドに部門名を事前に入力する例を示します。これは、「Source\$1URI」フィールドに URI 値に「financial」が含まれている場合に、ターゲットフィールド「Department」にドキュメントのターゲット値「Finance」を事前に入力するという条件を使用します。

**例 2:「Department」フィールドを作成し、条件を使用してドキュメントに関連付けられた部門名を事前に入力します。**

基本操作が適用される前のデータ。


| **Document\$1ID** | **Body\$1Text** | **Source\$1URI** | 
| --- | --- | --- | 
| 1 | Lorem Ipsum。 | financial/1 | 
| 2 | Lorem Ipsum。 | financial/2 | 
| 3 | Lorem Ipsum。 | financial/3 | 

基本操作が適用された後のデータ。


| **Document\$1ID** | **Body\$1Text** | **Source\$1URI** | **Department** | 
| --- | --- | --- | --- | 
| 1 | Lorem Ipsum。 | financial/1 | 財務 | 
| 2 | Lorem Ipsum。 | financial/2 | 財務 | 
| 3 | Lorem Ipsum。 | financial/3 | 財務 | 

**注記**  
Amazon Kendra インデックスフィールドとしてまだ作成されていない場合、 はターゲットドキュメントフィールドを作成できません。インデックスフィールドを作成したら、 を使用してドキュメントフィールドを作成できます`DocumentAttributeTarget`。 Amazon Kendra 次に、 は新しく作成したドキュメントメタデータフィールドをインデックスフィールドにマッピングします。

次のコードは、ドキュメントに関連付けられている顧客識別番号を削除するための基本的なデータ操作を設定する例です。

------
#### [ Console ]

**顧客識別番号を削除するための基本的なデータ操作を構成するには**

1. 左側のナビゲーションペインの **[Indexes]** (インデックス) で、**[Document enrichments]** (ドキュメントのエンリッチメント) を選択して、**[Add document enrichment]** (ドキュメントのエンリッチメントを追加) を選択します。

1. **[基本的な操作の設定]** ページで、ドキュメントのフィールドとコンテンツを変更するデータソースをドロップダウンから選択します。次に、ドロップダウンからドキュメントフィールド名「Customer\$1ID」を選択し、ドロップダウンからインデックスフィールド名「Customer\$1ID」を選択し、ドロップダウンからターゲットアクション **[Delete]** (削除) を選択します。次に、**[Add basic operation]** (基本的な演算の追加) を選択します。

------
#### [ CLI ]

**顧客識別番号を削除するための基本的なデータ操作を構成するには**

```
aws kendra create-data-source \
 --name data-source-name \
 --index-id index-id \
 --role-arn arn:aws:iam::account-id:role/role-name \
 --type S3 \
 --configuration '{"S3Configuration":{"BucketName":"S3-bucket-name"}}' \
 --custom-document-enrichment-configuration '{"InlineConfigurations":[{"Target":{"TargetDocumentAttributeKey":"Customer_ID", "TargetDocumentAttributeValueDeletion": true}}]}'
```

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

**顧客識別番号を削除するための基本的なデータ操作を構成するには**

```
import boto3
from botocore.exceptions import ClientError
import pprint
import time

kendra = boto3.client("kendra")

print("Create a data source with customizations")

# Provide the name of the data source
name = "data-source-name"
# Provide the index ID for the data source
index_id = "index-id"
# Provide the IAM role ARN required for data sources
role_arn = "arn:aws:iam::${account-id}:role/${role-name}"
# Provide the data source connection information
data_source_type = "S3"
S3_bucket_name = "S3-bucket-name"
# Configure the data source with Custom Document Enrichment
configuration = {"S3Configuration":
        {
            "BucketName": S3_bucket_name
        }
    }
custom_document_enrichment_configuration = {"InlineConfigurations":[
        {
            "Target":{"TargetDocumentAttributeKey":"Customer_ID",
                       "TargetDocumentAttributeValueDeletion": True}
        }]
    }

try:
    data_source_response = kendra.create_data_source(
        Name = name,
        IndexId = index_id,
        RoleArn = role_arn,
        Type = data_source_type
        Configuration = configuration
        CustomDocumentEnrichmentConfiguration = custom_document_enrichment_configuration
    )

    pprint.pprint(data_source_response)

    data_source_id = data_source_response["Id"]

    print("Wait for Amazon Kendra to create the data source with your customizations.")

    while True:
        # Get the details of the data source, such as the status
        data_source_description = kendra.describe_data_source(
            Id = data_source_id,
            IndexId = index_id
        )
        status = data_source_description["Status"]
        print(" Creating data source. Status: "+status)
        time.sleep(60)
        if status != "CREATING":
            break

    print("Synchronize the data source.")

    sync_response = kendra.start_data_source_sync_job(
        Id = data_source_id,
        IndexId = index_id
    )

    pprint.pprint(sync_response)

    print("Wait for the data source to sync with the index.")

    while True:

        jobs = kendra.list_data_source_sync_jobs(
            Id= data_source_id,
            IndexId= index_id
        )

        # For this example, there should be one job
        status = jobs["History"][0]["Status"]

        print(" Syncing data source. Status: "+status)
        time.sleep(60)
        if status != "SYNCING":
            break

except  ClientError as e:
        print("%s" % e)

print("Program ends.")
```

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

**顧客識別番号を削除するための基本的なデータ操作を構成するには**

```
package com.amazonaws.kendra;

import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.services.kendra.KendraClient;
import software.amazon.awssdk.services.kendra.model.CreateDataSourceRequest;
import software.amazon.awssdk.services.kendra.model.CreateDataSourceResponse;
import software.amazon.awssdk.services.kendra.model.CreateIndexRequest;
import software.amazon.awssdk.services.kendra.model.CreateIndexResponse;
import software.amazon.awssdk.services.kendra.model.DataSourceConfiguration;
import software.amazon.awssdk.services.kendra.model.DataSourceStatus;
import software.amazon.awssdk.services.kendra.model.DataSourceSyncJob;
import software.amazon.awssdk.services.kendra.model.DataSourceSyncJobStatus;
import software.amazon.awssdk.services.kendra.model.DataSourceType;
import software.amazon.awssdk.services.kendra.model.DescribeDataSourceRequest;
import software.amazon.awssdk.services.kendra.model.DescribeDataSourceResponse;
import software.amazon.awssdk.services.kendra.model.DescribeIndexRequest;
import software.amazon.awssdk.services.kendra.model.DescribeIndexResponse;
import software.amazon.awssdk.services.kendra.model.IndexStatus;
import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsRequest;
import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsResponse;
import software.amazon.awssdk.services.kendra.model.S3DataSourceConfiguration;
import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobRequest;
import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobResponse;

public class CreateDataSourceWithCustomizationsExample {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Create a data source with customizations");
        
        String dataSourceName = "data-source-name";
        String indexId = "index-id";
        String dataSourceRoleArn = "arn:aws:iam::account-id:role/role-name";
        String s3BucketName = "S3-bucket-name"

        KendraClient kendra = KendraClient.builder().build();
        
        CreateDataSourceRequest createDataSourceRequest = CreateDataSourceRequest
            .builder()
            .name(dataSourceName)
            .description(experienceDescription)
            .roleArn(experienceRoleArn)
            .type(DataSourceType.S3)
            .configuration(
                DataSourceConfiguration
                    .builder()
                    .s3Configuration(
                        S3DataSourceConfiguration
                            .builder()
                            .bucketName(s3BucketName)
                            .build()
                    ).build()
            )
            .customDocumentEnrichmentConfiguration(
                CustomDocumentEnrichmentConfiguration
                    .builder()
                    .inlineConfigurations(Arrays.asList(
                        InlineCustomDocumentEnrichmentConfiguration
                            .builder()
                            .target(
                                DocumentAttributeTarget
                                    .builder()
                                    .targetDocumentAttributeKey("Customer_ID")
                                    .targetDocumentAttributeValueDeletion(true)
                                    .build())
                            .build()
                    )).build();
        
        CreateDataSourceResponse createDataSourceResponse = kendra.createDataSource(createDataSourceRequest);
        System.out.println(String.format("Response of creating data source: %s", createDataSourceResponse));

        String dataSourceId = createDataSourceResponse.id();
        System.out.println(String.format("Waiting for Kendra to create the data source %s", dataSourceId));
        DescribeDataSourceRequest describeDataSourceRequest = DescribeDataSourceRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();

        while (true) {
            DescribeDataSourceResponse describeDataSourceResponse = kendra.describeDataSource(describeDataSourceRequest);

            DataSourceStatus status = describeDataSourceResponse.status();
            System.out.println(String.format("Creating data source. Status: %s", status));
            TimeUnit.SECONDS.sleep(60);
            if (status != DataSourceStatus.CREATING) {
                break;
            }
        }

        System.out.println(String.format("Synchronize the data source %s", dataSourceId));
        StartDataSourceSyncJobRequest startDataSourceSyncJobRequest = StartDataSourceSyncJobRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();
        StartDataSourceSyncJobResponse startDataSourceSyncJobResponse = kendra.startDataSourceSyncJob(startDataSourceSyncJobRequest);
        System.out.println(String.format("Waiting for the data source to sync with the index %s for execution ID %s", indexId, startDataSourceSyncJobResponse.executionId()));

        // For this example, there should be one job
        ListDataSourceSyncJobsRequest listDataSourceSyncJobsRequest = ListDataSourceSyncJobsRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();

        while (true) {
            ListDataSourceSyncJobsResponse listDataSourceSyncJobsResponse = kendra.listDataSourceSyncJobs(listDataSourceSyncJobsRequest);
            DataSourceSyncJob job = listDataSourceSyncJobsResponse.history().get(0);
            System.out.println(String.format("Syncing data source. Status: %s", job.status()));

            TimeUnit.SECONDS.sleep(60);
            if (job.status() != DataSourceSyncJobStatus.SYNCING) {
                break;
            }

        }

        System.out.println("Data source creation with customizations is complete");
    }
}
```

------

## Lambda 関数:メタデータまたはコンテンツの抽出と変更
<a name="advanced-data-manipulation"></a>

Lambda 関数を使用して、ドキュメントのフィールド、およびコンテンツを操作できます。これは、基本ロジックを超えて高度なデータ操作を適用する場合に便利です。例えば、画像上のテキストを解釈し、各画像をテキストドキュメントとして扱う、光学文字認識 (OCR) を使用します。または、特定のタイムゾーンで現在の日付/時間を取得し、日付フィールドに空の値がある日付/時刻を挿入します。

まず基本ロジックを適用し、Lambda 関数を使用してデータをさらに操作でき、その逆も可能です。Lambda 関数のみを適用することもできます。

Amazon Kendra は Lambda 関数を呼び出して、[CustomDocumentEnrichmentConfiguration](https://docs.aws.amazon.com/kendra/latest/APIReference/API_CustomDocumentEnrichmentConfiguration.html) の一部として取り込みプロセス中に高度なデータ操作を適用できます。Lambda 関数を実行し、 Amazon S3 バケットにアクセスしてデータ操作の出力を保存するアクセス許可を含むロールを指定します。[IAM 「アクセスロール](https://docs.aws.amazon.com/kendra/latest/dg/iam-roles.html)」を参照してください。

Amazon Kendra は、元の raw ドキュメントまたは構造化された解析済みドキュメントに Lambda 関数を適用できます。[PreExtractionHookConfiguration](https://docs.aws.amazon.com/kendra/latest/APIReference/API_CustomDocumentEnrichmentConfiguration.html) を使用して、元のデータまたは raw データを受け取り、データ操作を適用する Lambda 関数を構成できます。構造化ドキュメントを取得し、[PostExtractionHookConfiguration](https://docs.aws.amazon.com/kendra/latest/APIReference/API_CustomDocumentEnrichmentConfiguration.html) を使用してデータ操作を適用する Lambda 関数を設定することもできます。 はドキュメントのメタデータとテキストを Amazon Kendra 抽出してドキュメントを構造化します。Lambda 関数は、必須のリクエストとレスポンスの構造に従う必要があります。詳細については、「[Lambda 関数のデータ制約](#cde-data-contracts-lambda)」を参照してください。

コンソールで Lambda 関数を設定するには、インデックスを選択し、ナビゲーションメニューの **[Document enrichments]** (ドキュメントのエンリッチメント) を選択します。**[Configure Lambda functions]** (Lambda 関数の設定) をクリックして、Lambda 関数を設定します。

`PreExtractionHookConfiguration` に設定できる Lambda 関数は 1 つのみ、`PostExtractionHookConfiguration` に設定できる Lambda 関数も 1 つのみです。ただし、Lambda 関数は必要とする他の関数を呼び出すことができます。`PreExtractionHookConfiguration` および `PostExtractionHookConfiguration` の両方またはいずれか 1 つを設定できます。`PreExtractionHookConfiguration` の Lambda 関数の実行時間が 5 分を超えないよう、また、`PostExtractionHookConfiguration` の Lambda 関数の実行時間が 1 分を超えないようにしてください。カスタムドキュメントエンリッチメントの設定は、これを設定しない場合 Amazon Kendra よりも、ドキュメントを に取り込むのに自然に時間がかかります。

条件が満たされた場合にのみ Lambda 関数を呼び出す Amazon Kendra ように を設定できます。たとえば、空の日時値がある場合、 が現在の日時を挿入する関数を呼び出す Amazon Kendra ように条件を指定できます。

次に、Lambda 関数を使用して OCR を実行して画像からテキストを解釈し、このテキストを「Document\$1Image\$1Text」というフィールドに保存する例を示します。

**例 1: 画像からテキストを抽出してテキストドキュメントを作成する**

高度な操作が適用される前のデータ。


| **Document\$1ID** | **Document\$1Image** | 
| --- | --- | 
| 1 | image\$11.png | 
| 2 | image\$12.png | 
| 3 | image\$13.png | 

高度な操作が適用された後のデータ。


| **Document\$1ID** | **Document\$1Image** | **Document\$1Image\$1Text** | 
| --- | --- | --- | 
| 1 | image\$11.png | メールでのアンケートの回答 | 
| 2 | image\$12.png | メールでのアンケートの回答 | 
| 3 | image\$13.png | メールでのアンケートの回答 | 

次に、Lambda 関数を使用して、空の日付値に対する現在の日付/時間を挿入する例を示します。これは、日付フィールドの値が「null」の場合、これを現在の日付/時刻に置き換えるという条件を使用します。

**例 2: Last\$1Updated フィールドの空の値を、現在の日付/時間で置き換える。**

高度な操作が適用される前のデータ。


| **Document\$1ID** | **Body\$1Text** | **Last\$1Updated** | 
| --- | --- | --- | 
| 1 | Lorem Ipsum。 | 2020 年 1 月 1 日 | 
| 2 | Lorem Ipsum。 |   | 
| 3 | Lorem Ipsum。 | 2020 年 7 月 1 日 | 

高度な操作が適用された後のデータ。


| **Document\$1ID** | **Body\$1Text** | **Last\$1Updated** | 
| --- | --- | --- | 
| 1 | Lorem Ipsum。 | 2020 年 1 月 1 日 | 
| 2 | Lorem Ipsum。 | 2021 年 12 月 1 日 | 
| 3 | Lorem Ipsum。 | 2020 年 7 月 1 日 | 

次のコードは、raw の元のデータに対して高度なデータ操作のための Lambda 関数を設定する例です。

------
#### [ Console ]

**raw の元のデータに対して高度なデータ操作のための Lambda 関数を設定するには**

1. 左側のナビゲーションペインの **[Indexes]** (インデックス) で、**[Document enrichments]** (ドキュメントのエンリッチメント) を選択して、**[Add document enrichment]** (ドキュメントのエンリッチメントを追加) を選択します。

1. **Lambda 関数の設定**ページで、**抽出前の Lambda** セクションで、Lambda 関数 ARN と Amazon S3 バケットのドロップダウンから を選択します。ドロップダウンから新しいロールを作成するオプションを選択して、 IAM アクセスロールを追加します。これにより、ドキュメントエンリッチメントを作成するために必要な Amazon Kendra アクセス許可が作成されます。

------
#### [ CLI ]

**raw の元のデータに対して高度なデータ操作のための Lambda 関数を設定するには**

```
aws kendra create-data-source \
 --name data-source-name \
 --index-id index-id \
 --role-arn arn:aws:iam::account-id:role/role-name \
 --type S3 \
 --configuration '{"S3Configuration":{"BucketName":"S3-bucket-name"}}' \
 --custom-document-enrichment-configuration '{"PreExtractionHookConfiguration":{"LambdaArn":"arn:aws:iam::account-id:function/function-name", "S3Bucket":"S3-bucket-name"}, "RoleArn": "arn:aws:iam:account-id:role/cde-role-name"}'
```

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

**raw の元のデータに対して高度なデータ操作のための Lambda 関数を設定するには**

```
import boto3
from botocore.exceptions import ClientError
import pprint
import time

kendra = boto3.client("kendra")

print("Create a data source with customizations.")

# Provide the name of the data source
name = "data-source-name"
# Provide the index ID for the data source
index_id = "index-id"
# Provide the IAM role ARN required for data sources
role_arn = "arn:aws:iam::${account-id}:role/${role-name}"
# Provide the data source connection information
data_source_type = "S3"
S3_bucket_name = "S3-bucket-name"
# Configure the data source with Custom Document Enrichment
configuration = {"S3Configuration":
        {
            "BucketName": S3_bucket_name
        }
    }
custom_document_enrichment_configuration = {"PreExtractionHookConfiguration":
        {
            "LambdaArn":"arn:aws:iam::account-id:function/function-name",
            "S3Bucket":"S3-bucket-name"
        }
    "RoleArn":"arn:aws:iam::account-id:role/cde-role-name"
    }

try:
    data_source_response = kendra.create_data_source(
        Name = name,
        IndexId = index_id,
        RoleArn = role_arn,
        Type = data_source_type
        Configuration = configuration
        CustomDocumentEnrichmentConfiguration = custom_document_enrichment_configuration
    )

    pprint.pprint(data_source_response)

    data_source_id = data_source_response["Id"]

    print("Wait for Amazon Kendra to create the data source with your customizations.")

    while True:
        # Get the details of the data source, such as the status
        data_source_description = kendra.describe_data_source(
            Id = data_source_id,
            IndexId = index_id
        )
        status = data_source_description["Status"]
        print(" Creating data source. Status: "+status)
        time.sleep(60)
        if status != "CREATING":
            break

    print("Synchronize the data source.")

    sync_response = kendra.start_data_source_sync_job(
        Id = data_source_id,
        IndexId = index_id
    )

    pprint.pprint(sync_response)

    print("Wait for the data source to sync with the index.")

    while True:

        jobs = kendra.list_data_source_sync_jobs(
            Id = data_source_id,
            IndexId = index_id
        )

        # For this example, there should be one job
        status = jobs["History"][0]["Status"]

        print(" Syncing data source. Status: "+status)
        time.sleep(60)
        if status != "SYNCING":
            break

except  ClientError as e:
        print("%s" % e)

print("Program ends.")
```

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

**raw の元のデータに対して高度なデータ操作のための Lambda 関数を設定するには**

```
package com.amazonaws.kendra;

import java.util.concurrent.TimeUnit;
import software.amazon.awssdk.services.kendra.KendraClient;
import software.amazon.awssdk.services.kendra.model.CreateDataSourceRequest;
import software.amazon.awssdk.services.kendra.model.CreateDataSourceResponse;
import software.amazon.awssdk.services.kendra.model.CreateIndexRequest;
import software.amazon.awssdk.services.kendra.model.CreateIndexResponse;
import software.amazon.awssdk.services.kendra.model.DataSourceConfiguration;
import software.amazon.awssdk.services.kendra.model.DataSourceStatus;
import software.amazon.awssdk.services.kendra.model.DataSourceSyncJob;
import software.amazon.awssdk.services.kendra.model.DataSourceSyncJobStatus;
import software.amazon.awssdk.services.kendra.model.DataSourceType;
import software.amazon.awssdk.services.kendra.model.DescribeDataSourceRequest;
import software.amazon.awssdk.services.kendra.model.DescribeDataSourceResponse;
import software.amazon.awssdk.services.kendra.model.DescribeIndexRequest;
import software.amazon.awssdk.services.kendra.model.DescribeIndexResponse;
import software.amazon.awssdk.services.kendra.model.IndexStatus;
import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsRequest;
import software.amazon.awssdk.services.kendra.model.ListDataSourceSyncJobsResponse;
import software.amazon.awssdk.services.kendra.model.S3DataSourceConfiguration;
import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobRequest;
import software.amazon.awssdk.services.kendra.model.StartDataSourceSyncJobResponse;


public class CreateDataSourceWithCustomizationsExample {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("Create a data source with customizations");
        
        String dataSourceName = "data-source-name";
        String indexId = "index-id";
        String dataSourceRoleArn = "arn:aws:iam::account-id:role/role-name";
        String s3BucketName = "S3-bucket-name"

        KendraClient kendra = KendraClient.builder().build();
        
        CreateDataSourceRequest createDataSourceRequest = CreateDataSourceRequest
            .builder()
            .name(dataSourceName)
            .description(experienceDescription)
            .roleArn(experienceRoleArn)
            .type(DataSourceType.S3)
            .configuration(
                DataSourceConfiguration
                    .builder()
                    .s3Configuration(
                        S3DataSourceConfiguration
                            .builder()
                            .bucketName(s3BucketName)
                            .build()
                    ).build()
            )
            .customDocumentEnrichmentConfiguration(
                CustomDocumentEnrichmentConfiguration
                    .builder()
                    .preExtractionHookConfiguration(
                        HookConfiguration
                            .builder()
                            .lambdaArn("arn:aws:iam::account-id:function/function-name")
                            .s3Bucket("S3-bucket-name")
                            .build())
                    .roleArn("arn:aws:iam::account-id:role/cde-role-name")
                    .build();
        
        CreateDataSourceResponse createDataSourceResponse = kendra.createDataSource(createDataSourceRequest);
        System.out.println(String.format("Response of creating data source: %s", createDataSourceResponse));

        String dataSourceId = createDataSourceResponse.id();
        System.out.println(String.format("Waiting for Kendra to create the data source %s", dataSourceId));
        DescribeDataSourceRequest describeDataSourceRequest = DescribeDataSourceRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();

        while (true) {
            DescribeDataSourceResponse describeDataSourceResponse = kendra.describeDataSource(describeDataSourceRequest);

            DataSourceStatus status = describeDataSourceResponse.status();
            System.out.println(String.format("Creating data source. Status: %s", status));
            TimeUnit.SECONDS.sleep(60);
            if (status != DataSourceStatus.CREATING) {
                break;
            }
        }

        System.out.println(String.format("Synchronize the data source %s", dataSourceId));
        StartDataSourceSyncJobRequest startDataSourceSyncJobRequest = StartDataSourceSyncJobRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();
        StartDataSourceSyncJobResponse startDataSourceSyncJobResponse = kendra.startDataSourceSyncJob(startDataSourceSyncJobRequest);
        System.out.println(String.format("Waiting for the data source to sync with the index %s for execution ID %s", indexId, startDataSourceSyncJobResponse.executionId()));

        // For this example, there should be one job
        ListDataSourceSyncJobsRequest listDataSourceSyncJobsRequest = ListDataSourceSyncJobsRequest
            .builder()
            .indexId(indexId)
            .id(dataSourceId)
            .build();

        while (true) {
            ListDataSourceSyncJobsResponse listDataSourceSyncJobsResponse = kendra.listDataSourceSyncJobs(listDataSourceSyncJobsRequest);
            DataSourceSyncJob job = listDataSourceSyncJobsResponse.history().get(0);
            System.out.println(String.format("Syncing data source. Status: %s", job.status()));

            TimeUnit.SECONDS.sleep(60);
            if (job.status() != DataSourceSyncJobStatus.SYNCING) {
                break;
            }

        }

        System.out.println("Data source creation with customizations is complete");
    }
}
```

------

## Lambda 関数のデータ制約
<a name="cde-data-contracts-lambda"></a>

高度なデータ操作のための Lambda 関数は、 Amazon Kendra データコントラクトと連携します。制約は、Lambda 関数の必須のリクエストとレスポンスの構造です。Lambda 関数がこれらの構造に従わない場合、 はエラーを Amazon Kendra スローします。

`PreExtractionHookConfiguration` の Lambda 関数は、次のリクエスト構造を期待します。

```
{
    "version": <str>,
    "dataBlobStringEncodedInBase64": <str>, //In the case of a data blob
    "s3Bucket": <str>, //In the case of an S3 bucket
    "s3ObjectKey": <str>, //In the case of an S3 bucket
    "metadata": <Metadata>
}
```

`metadata` 構造。これには、つぎの `CustomDocumentAttribute` 構造を含みます。

```
{
    "attributes": [<CustomDocumentAttribute<]
}

CustomDocumentAttribute
{
    "name": <str>,
    "value": <CustomDocumentAttributeValue>
}

CustomDocumentAttributeValue
{
    "stringValue": <str>,
    "integerValue": <int>,
    "longValue": <long>,
    "stringListValue": list<str>,
    "dateValue": <str>
}
```

`PreExtractionHookConfiguration` の Lambda 関数は、以下のレスポンス構造に従う必要があります。

```
{
    "version": <str>,
    "dataBlobStringEncodedInBase64": <str>, //In the case of a data blob
    "s3ObjectKey": <str>, //In the case of an S3 bucket
    "metadataUpdates": [<CustomDocumentAttribute>]
}
```

`PostExtractionHookConfiguration` の Lambda 関数は、次のリクエスト構造を期待します。

```
{
    "version": <str>,
    "s3Bucket": <str>,
    "s3ObjectKey": <str>,
    "metadata": <Metadata>
}
```

`PostExtractionHookConfiguration` の Lambda 関数は、以下のレスポンス構造に従う必要があります。

```
PostExtractionHookConfiguration Lambda Response
{
    "version": <str>,
    "s3ObjectKey": <str>,
    "metadataUpdates": [<CustomDocumentAttribute>]
}
```

変更されたドキュメントが Amazon S3 バケットにアップロードされます。変更されたドキュメントは、[構造化ドキュメントの形式](#structured-document-format) に示す形式に従う必要があります。

### 構造化ドキュメントの形式
<a name="structured-document-format"></a>

Amazon Kendra は、構造化ドキュメントを特定の Amazon S3 バケットにアップロードします。構造化ドキュメントは、次の形式に従います。

```
Kendra document

{
   "textContent": <TextContent>
}

TextContent
{
  "documentBodyText": <str>
}
```

### データ制約に準拠する Lambda 関数の例
<a name="example-lambda-function-advanced-manipulation"></a>

次の Python コードは、メタデータフィールド `_authors`、`_document_title` および raw の元のドキュメントの本文の高度な操作を適用する Lambda 関数の例です。

** Amazon S3 バケットに存在する本文コンテンツの場合**

```
import json
import boto3
     
s3 = boto3.client("s3")

# Lambda function for advanced data manipulation    
def lambda_handler(event, context):
    # Get the value of "S3Bucket" key name or item from the given event input
    s3_bucket = event.get("s3Bucket")
    # Get the value of "S3ObjectKey" key name or item from the given event input
    s3_object_key = event.get("s3ObjectKey")
    
    content_object_before_CDE = s3.get_object(Bucket = s3_bucket, Key = s3_object_key)
    content_before_CDE = content_object_before_CDE["Body"].read().decode("utf-8");
    content_after_CDE = "CDEInvolved " + content_before_CDE
    
    # Get the value of "metadata" key name or item from the given event input
    metadata = event.get("metadata")
    # Get the document "attributes" from the metadata 
    document_attributes = metadata.get("attributes")
    
    s3.put_object(Bucket = s3_bucket, Key = "dummy_updated_kendra_document", Body=json.dumps(content_after_CDE))
    return {
        "version": "v0",
        "s3ObjectKey": "dummy_updated_kendra_document",
        "metadataUpdates": [
            {"name":"_document_title", "value":{"stringValue":"title_from_pre_extraction_lambda"}},
            {"name":"_authors", "value":{"stringListValue":["author1", "author2"]}}
        ]
    }
```

**本文がデータ BLOB に存在する場合**

```
import json
import boto3
import base64

# Lambda function for advanced data manipulation
def lambda_handler(event, context):
    
    # Get the value of "dataBlobStringEncodedInBase64" key name or item from the given event input 
    data_blob_string_encoded_in_base64 = event.get("dataBlobStringEncodedInBase64")
    # Decode the data blob string in UTF-8
    data_blob_string = base64.b64decode(data_blob_string_encoded_in_base64).decode("utf-8")
    # Get the value of "metadata" key name or item from the given event input    
    metadata = event.get("metadata")
    # Get the document "attributes" from the metadata
    document_attributes = metadata.get("attributes")
    
    new_data_blob = "This should be the modified data in the document by pre processing lambda ".encode("utf-8")
    return {
        "version": "v0",
        "dataBlobStringEncodedInBase64": base64.b64encode(new_data_blob).decode("utf-8"),
        "metadataUpdates": [
            {"name":"_document_title", "value":{"stringValue":"title_from_pre_extraction_lambda"}},
            {"name":"_authors", "value":{"stringListValue":["author1", "author2"]}}
        ]
    }
```

次の Python コードは、メタデータフィールド `_authors`、`_document_title` および構造化されたドキュメントまたは解析済みのドキュメントの本文の高度な操作を適用する Lambda 関数の例です。

```
import json
import boto3
import time

s3 = boto3.client("s3")

# Lambda function for advanced data manipulation
def lambda_handler(event, context):
    
    # Get the value of "S3Bucket" key name or item from the given event input
    s3_bucket = event.get("s3Bucket")
    # Get the value of "S3ObjectKey" key name or item from the given event input
    s3_key = event.get("s3ObjectKey")
    # Get the value of "metadata" key name or item from the given event input
    metadata = event.get("metadata")
    # Get the document "attributes" from the metadata 
    document_attributes = metadata.get("attributes")
    
    kendra_document_object = s3.get_object(Bucket = s3_bucket, Key = s3_key)
    kendra_document_string = kendra_document_object['Body'].read().decode('utf-8')
    kendra_document = json.loads(kendra_document_string)
    kendra_document["textContent"]["documentBodyText"] = "Changing document body to a short sentence."
    
    s3.put_object(Bucket = s3_bucket, Key = "dummy_updated_kendra_document", Body=json.dumps(kendra_document))

    return {
        "version" : "v0",
        "s3ObjectKey": "dummy_updated_kendra_document",
        "metadataUpdates": [
            {"name": "_document_title", "value":{"stringValue": "title_from_post_extraction_lambda"}},
            {"name": "_authors", "value":{"stringListValue":["author1", "author2"]}}
        ]
    }
```