【Amazon Kendra】Web Crawler connector v2.0で追加されたField Mappingの使い方

Amazon Kendraのデータソースである「Web Crawler connector v2.0」(以下Crawler v2)より追加された機能のうちの一つとして「Field Mapping」があります。

# できること
- HTML内の任意のmetaタグを取得し、Index Fieldとして登録、利用が可能になります。
    - 作成するのはデータソース作成時ですが、作成と同時にインデックスの「Facet definition」から確認できる「Index Field」にも作成されます。
        - 作成した「Index Field」は名前とデータ型を<font color="red">**削除も変更もできない**</font>ので注意（2023/11/28時点）

以下の設定で```sample_string_site.html```をクロールした場合、Index FieldでField Name「Servise」にString型の値「Amazon Kendra」が登録されます。
- KendraのCrawler v2作成または変更画面からStep 4.「Set field mappings」内の「Add field」
![スクリーンショット 2023-10-29 23.01.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/e03ce2fa-f924-3f65-f056-9cf870aad116.png)

```sample_string_site.html
・
・
<head>

  <meta name="keyword" content="Amazon Kendra"> 
  
  <title>Document</title>
</head>
.
.
```

## Date型のデータタイプ

- Crawler v2の作成、変更画面からDate型のデータ型は提供されていません。（2023/11/28時点）
![スクリーンショット 2023-11-07 2.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/0c2b9791-69cd-190f-5635-1aaa9c15436c.png)



- そのため、あらかじめDate型のIndex Fieldを作成し、仮のString型のデータ型に登録し、[Custom Document Enrichment](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html)（以下CDE）でDate型のIndex Fieldに登録し直す必要があります。
    - Crawler v2はbodyタグ内のみインデックスの情報として持つため、一旦Field Mappingでmetaタグから取得しCDE内で利用可能にする必要があります。
    - 値としてはDate型となっていますが、ISO8601形式であれば分単位まで登録可能で、[QueryAPI](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/kendra/client/query.html)で分以下の単位で絞り込み可能です。

- 以下はサンプルサイトとCDEとして処理を行うLambdaのサンプルになります。
    - インデックスのDate型のIndex Fieldとデータソースの仮のString型のField Mappingは省略
    - 一時的に日時の情報を持つtmp_sample_datetimeをDate型のsample_datetimeに登録しています。
```sample_datetime_site.html
・
・
<head>

  <meta name="test_datetime" content="2023-11-07T12:30:00Z"> 
  
  <title>Document</title>
</head>
.
.
```

```sample_PreExtractionHookConfiguration.py
def lambda_handler(event, context):
    attributes = event["metadata"].get("attributes")
    updatedMeta = []

    for attribute in attributes:
        if attribute["name"] == "tmp_sample_datetime":
            updatedMeta.append(
                {
                    "name": "sample_datetime",
                    "value": {"dateValue": attribute["value"].get("stringValue")},
                }
            )

    return {
        "version": "v0",
        "s3ObjectKey": event.get("s3ObjectKey"),
        "metadataUpdates": updatedMeta,
    }
```

- これで一旦登録は可能ですが、持ってる値がDateValueではなく、StringValueなのが気になるのが今後の課題です。。
![c0e29f92-6f00-4a92-8cd0-99918f2cad82.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/d61cec2c-69b9-0c70-29a6-0a8bb144c2c2.png)

## String Listのデータタイプ
- Crawler v2は同じnameを持つmetaタグがある場合、一つ目のものしか取得しない（後述）ため、以下の例のようにコンマで区切り、CDEで利用可能にしたのち、Lambdaにて再度更新をかける必要があります。
![スクリーンショット 2023-11-09 22.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/ee466ebd-c113-797c-0580-b3c445364f91.png)

```sample_string_list_site.html
.
.
<head>

  <meta name="test_string_list" content="test_string_list_1,test_string_list_2" />
  
  <title>Document</title>
</head>
.
.
```

```sample_PreExtractionHookConfiguration.py
def lambda_handler(event, context):
    attributes = event["metadata"].get("attributes")
    updatedMeta = []

    for attribute in attributes:
        if attribute["name"] == "string_list":
            updatedMeta.append(
                {
                    "name": "categories",
                    "value": {
                        "stringListValue": attribute["value"]
                        .get("stringListValue")[0]
                        .split(",")
                    },
                }
            )

    return {
        "version": "v0",
        "s3ObjectKey": event.get("s3ObjectKey"),
        "metadataUpdates": updatedMeta,
    }

```
![スクリーンショット 2023-11-09 22.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/fb9c4a9e-f00f-c4d3-57ef-ee999aa74927.png)

- CDEで処理を行わない場合、以下のように分けて判定されない。
![スクリーンショット 2023-11-09 22.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/eb5b9a6d-02b9-8d17-934b-082e7719c686.png)

## 同じnameを持つmetaタグがある場合
- 同様のField Mappingでクロールした結果、一つ目のものしか取得されない。
```sample_string_list_site_case.html
.
.
<head>

  <meta name="test_string_list" content="test_string_list_1" />
  <meta name="test_string_list" content="test_string_list_2" />
  
  <title>Document</title>
</head>
.
.
```
![d67c5946-1ca7-4806-8eae-fad594e857a5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/6796c094-184e-4d6d-8c62-5b2b217533db.png)



## 他に検証したがうまくいかなかったパターン
- その1
```
<meta
  name="test_string_list"
  content="['test_string_list_1','test_string_list_2']"
/>
```

![b82230dc-5438-4551-8f92-4415dceac7f0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/37364ca5-f003-2439-0390-fb67cf8b3a6d.png)

- その2
```
<meta
  name="test_string_list"
  content="[test_string_list_1,test_string_list_2]"
/>
```
![88e33a97-c8a2-40b3-8c62-a6c275d90ab1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617563/4c668bfe-e196-e6ab-6647-cb1c3a3d4676.png)
# 参考資料
- [Amazon Kendra Web Crawler connector v2.0](https://docs.aws.amazon.com/kendra/latest/dg/data-source-v2-web-crawler.html)
- [amazon-kendra-cde-examples](https://github.com/aws-samples/amazon-kendra-cde-examples)
- [Kendra Custom field mappings](https://repost.aws/questions/QULy8kRh2eRx2JtcI2_bLi3w/kendra-custom-field-mappings)
- [Enriching your documents during ingestion](https://docs.aws.amazon.com/kendra/latest/dg/custom-document-enrichment.html)