Azure AI 検索でクエリを実行するために Azure Cosmos DB for NoSQL からデータのインデックスを付ける

この記事では、インデクサーを構成する方法について説明します。これにより、Azure Cosmos DB for NoSQL からコンテンツがインポートされて、Azure AI Search で検索できるようになります。

この記事では、Cosmos DB に固有の情報を使用して、インデクサーの作成に関する記事を補足しています。 REST API を使用して、すべてのインデクサーに共通する 3 部構成のワークフロー (データ ソースの作成、インデックスの作成、インデクサーの作成) を示します。 データ抽出は、インデクサーの作成要求を送信したときに発生します。

用語が混乱を招く可能性があるため、Azure Cosmos DB のインデックス作成Azure AI Search のインデックス作成は異なる操作であることに注意してください。 Azure AI Search のインデックス作成では、検索インデックスが作成され、検索サービスに読み込まれます。

前提条件

データ ソースを定義する

データ ソース定義では、インデックスを付けるデータ、資格情報、データの変更を識別するためのポリシーを指定します。 データ ソースは、複数のインデクサーで使用できる独立したリソースです。

  1. データ ソースを作成または更新してその定義を設定します。

    POST https://[service name].search.windows.net/datasources?api-version=2023-11-01
    Content-Type: application/json
    api-key: [Search service admin key]
    {
        "name": "[my-cosmosdb-ds]",
        "type": "cosmosdb",
        "credentials": {
          "connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.com;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]"
        },
        "container": {
          "name": "[my-cosmos-db-collection]",
          "query": null
        },
        "dataChangeDetectionPolicy": {
          "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
        "  highWaterMarkColumnName": "_ts"
        },
        "dataDeletionDetectionPolicy": null,
        "encryptionKey": null,
        "identity": null
    }
    
  2. "type" を "cosmosdb" に指定します (必須)。 古い Search API バージョン 2017-11-11 を使用している場合、"type" の構文は "documentdb" です。 それ以外 (2019-05-06 以降) の場合は、"cosmosdb" を使用します。

  3. "credentials" を接続文字列に設定します。 続く部分は、サポートされている形式を記述します。

  4. "container" をコレクションに設定します。 "name" プロパティは必須です。これによって、インデックスが作成されるデータベース コレクションの ID を指定します。 "query" プロパティは省略可能です。 これは、任意の JSON ドキュメントをフラット化して、Azure AI Search でインデックスを作成できるフラット スキーマにするために使用します。

  5. データが変化しやすいので、以降の実行で新規および更新された項目だけをインデクサーで取得する場合は、"dataChangeDetectionPolicy" を設定します。

  6. ソース項目が削除されたら場合に検索インデックスから検索ドキュメントを削除する場合は、"dataDeletionDetectionPolicy" を設定します。

サポートされている資格情報と接続文字列

インデクサーは、次の接続を使用してコレクションに接続できます。

エンドポイント URL にポート番号は含めないでください。 ポート番号を含めると、接続は失敗します。

フル アクセス接続文字列
{ "connectionString" : "AccountEndpoint=https://<Cosmos DB account name>.documents.azure.com;AccountKey=<Cosmos DB auth key>;Database=<Cosmos DB database id>" }`
Azure portal の Azure Cosmos DB アカウント ページから接続文字列を取得するには、左側のナビゲーション ウィンドウの [キー] を選びます。 キーだけではなく、完全な接続文字列を選択してください。
マネージド ID の接続文字列
{ "connectionString" : "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.DocumentDB/databaseAccounts/<your cosmos db account name>/;(ApiKind=[api-kind];)/(IdentityAuthType=[identity-auth-type])" }
この接続文字列にアカウント キーは必要ありませんが、マネージド ID を使用して接続できる検索サービスが必要です。 SQL API をターゲットとする接続の場合は、接続文字列から ApiKind を省略できます。 ApiKind の詳細については、IdentityAuthTypeマネージド ID を使用して Azure Cosmos DB データベースへのインデクサー接続を設定する方法に関する記事を参照してください

インデックス作成するデータの処理にクエリを活用する

"container" の下にある "query" プロパティで、SQL クエリを指定して、ネストされたプロパティや配列のフラット化、JSON プロパティのプロジェクション、インデックスを作成するデータのフィルター処理を行うことができます。

ドキュメントのサンプル:

    {
        "userId": 10001,
        "contact": {
            "firstName": "andy",
            "lastName": "hoh"
        },
        "company": "microsoft",
        "tags": ["azure", "cosmosdb", "search"]
    }

フィルター処理クエリ:

SELECT * FROM c WHERE c.company = "microsoft" and c._ts >= @HighWaterMark ORDER BY c._ts

平坦化クエリ:

SELECT c.id, c.userId, c.contact.firstName, c.contact.lastName, c.company, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

プロジェクション クエリ:

SELECT VALUE { "id":c.id, "Name":c.contact.firstName, "Company":c.company, "_ts":c._ts } FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

配列を平坦化するクエリ:

SELECT c.id, c.userId, tag, c._ts FROM c JOIN tag IN c.tags WHERE c._ts >= @HighWaterMark ORDER BY c._ts

サポートされていないクエリ (DISTINCT と GROUP BY)

DISTINCT キーワードまたは GROUP BY 句を使用するクエリはサポートされていません。 Azure AI Search は、クエリの結果を完全に列挙するために、SQL クエリの改ページに依存します。 DISTINCT キーワードと GROUP BY 句はどちらも、結果の改ページに使用される継続トークンに対応していません。

サポートされていないクエリの例を以下に示します。

SELECT DISTINCT c.id, c.userId, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts

SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name

SELECT TOP 4 COUNT(1) AS foodGroupCount, f.foodGroup FROM Food f GROUP BY f.foodGroup

Azure Cosmos DB では、ORDER BY 句を使用した DISTINCT キーワードによる SQL クエリの改ページをサポートするための回避策がありますが、これは Azure AI Search には対応していません。 クエリでは 1 つの JSON 値が返されるのに対し、Azure AI Search では JSON オブジェクトを受け取る必要があります。

-- The following query returns a single JSON value and isn't supported by Azure AI Search
SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name

インデックスに検索フィールドを追加する

検索インデックスに、ソース JSON ドキュメントまたはカスタム クエリ プロジェクションの出力を受け入れるフィールドを追加します。 検索インデックス スキーマがソース データに対応していることを確認してください。 Azure Cosmos DB 内のコンテンツの場合、検索インデックス スキーマは、データ ソース内の Azure Cosmos DB の項目に対応している必要があります。

  1. インデックスを作成または更新して、データを格納する検索フィールドを定義します。

    POST https://[service name].search.windows.net/indexes?api-version=2023-11-01
    Content-Type: application/json
    api-key: [Search service admin key]
    {
        "name": "mysearchindex",
        "fields": [{
            "name": "rid",
            "type": "Edm.String",
            "key": true,
            "searchable": false
        }, 
        {
            "name": "description",
            "type": "Edm.String",
            "filterable": false,
            "searchable": true,
            "sortable": false,
            "facetable": false,
            "suggestions": true
        }
      ]
    }
    
  2. ドキュメント キー フィールド ("key": true) を作成します。 パーティション分割されたコレクションの場合、既定のドキュメント キーは Azure Cosmos DB の _rid プロパティですが、フィールド名の先頭にはアンダースコア文字を使用できないため、これは Azure AI Search によって rid に自動的に変更されます。 また、Azure Cosmos DB の _rid 値には、Azure AI Search キーでは無効な文字が含まれています。 そのため、_rid 値は Base64 でエンコードされます。

  3. さらに多くの検索可能なコンテンツを使用する場合は、フィールドをさらに作成します。 詳細については、インデックスの作成に関するページを参照してください。

マッピング データ型

JSON データ型 Azure AI Search のフィールドの型
Bool Edm.Boolean、Edm.String
整数などの数値 Edm.Int32、Edm.Int64、Edm.String
浮動小数点などの数値 Edm.Double、Edm.String
String Edm.String
["a", "b", "c"] などのプリミティブ型の配列 Collection(Edm.String)
日付などの文字列 Edm.DateTimeOffset、Edm.String
{ "type": "Point", "coordinates": [long, lat] } などの GeoJSON オブジェクト Edm.GeographyPoint
その他の JSON オブジェクト 該当なし

Azure Cosmos DB for NoSQL インデクサーを構成して実行する

インデックスとデータ ソースを作成したら、インデクサーを作成できます。 インデクサーの構成では、実行時の動作を制御する入力、パラメーター、プロパティを指定します。

  1. 名前を指定し、データ ソースとターゲット インデックスを参照することで、インデクサーを作成または更新します。

    POST https://[service name].search.windows.net/indexers?api-version=2023-11-01
    Content-Type: application/json
    api-key: [search service admin key]
    {
        "name" : "[my-cosmosdb-indexer]",
        "dataSourceName" : "[my-cosmosdb-ds]",
        "targetIndexName" : "[my-search-index]",
        "disabled": null,
        "schedule": null,
        "parameters": {
            "batchSize": null,
            "maxFailedItems": 0,
            "maxFailedItemsPerBatch": 0,
            "base64EncodeKeys": false,
            "configuration": {}
            },
        "fieldMappings": [],
        "encryptionKey": null
    }
    
  2. フィールドの名前または種類に違いがある、または検索インデックスで複数のソース フィールドのバージョンが必要な場合、フィールド マッピングを定義します。

  3. その他のプロパティについては、「インデクサーの作成方法」を参照してください。

インデクサーは、作成されると自動的に実行されます。 これを防ぐには、"disabled" を true に設定します。 インデクサーの実行を制御するには、インデクサーをオンデマンドで実行するか、スケジュールを設定します。

インデクサーの状態を確認する

インデクサーの状態と実行履歴を監視するには、インデクサーの状態の取得要求を送信します。

GET https://myservice.search.windows.net/indexers/myindexer/status?api-version=2023-11-01
  Content-Type: application/json  
  api-key: [admin key]

応答には、状態と処理された項目の数が含まれます。 次の例のように表示されます。

    {
        "status":"running",
        "lastResult": {
            "status":"success",
            "errorMessage":null,
            "startTime":"2022-02-21T00:23:24.957Z",
            "endTime":"2022-02-21T00:36:47.752Z",
            "errors":[],
            "itemsProcessed":1599501,
            "itemsFailed":0,
            "initialTrackingState":null,
            "finalTrackingState":null
        },
        "executionHistory":
        [
            {
                "status":"success",
                "errorMessage":null,
                "startTime":"2022-02-21T00:23:24.957Z",
                "endTime":"2022-02-21T00:36:47.752Z",
                "errors":[],
                "itemsProcessed":1599501,
                "itemsFailed":0,
                "initialTrackingState":null,
                "finalTrackingState":null
            },
            ... earlier history items
        ]
    }

実行履歴には、最近完了した実行 50 件が含まれます。時系列の逆の順に並べられるため、最後の実行が最初に表示されます。

新規および変更されたドキュメントのインデックス作成

インデクサーで検索インデックスが完全に設定されたら、以降のインデクサーで、データベース内の新規および変更されたドキュメントだけのインデックスを増分的に作成することができます。

増分インデックス作成を有効にするには、データ ソース定義で "dataChangeDetectionPolicy" プロパティを設定します。 このプロパティで、データに対して使用する変更追跡メカニズムをインデクサーに指示します。

Azure Cosmos DB インデクサーの場合、唯一サポートされているポリシーは、Azure Cosmos DB によって指定される _ts (timestamp) プロパティを使用する HighWaterMarkChangeDetectionPolicy です。

次の例は、変更検出ポリシーを含むデータ ソース定義を示しています。

"dataChangeDetectionPolicy": {
    "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"  highWaterMarkColumnName": "_ts"
},

増分インデックス作成とカスタム クエリ

ドキュメントを取得するためにカスタム クエリを使用している場合は、そのクエリで結果が _ts 列の順に並べ替えられていることを確認してください。 こうすることで Azure AI Search が使用する定期的なチェックポイントが作成され、エラーが発生した場合に増分の進行状況を利用できます。

ただし状況によっては、クエリに ORDER BY [collection alias]._ts 句が含まれる場合でも、クエリ結果が _ts で並べ替えられることを Azure AI Search で推論されない可能性があります。 assumeOrderByHighWaterMarkColumn 構成プロパティの設定で結果が並べ替えられるように Azure AI Search に指示することもできます。

このヒントを指定するには、次のようにインデクサー定義を作成または更新します。

{
    ... other indexer definition properties
    "parameters" : {
        "configuration" : { "assumeOrderByHighWaterMarkColumn" : true } }
} 

削除されたドキュメントのインデックス作成

コレクションから行が削除されると、通常、検索インデックスからも同様に行を削除する必要があります。 データ削除の検出ポリシーの目的は、削除されたデータ項目を効率的に識別することです。 現在、唯一サポートされているポリシーは、Soft Delete ポリシー (削除されると何らかのフラグでマークされる) です。これは、データ ソース定義で次のように指定します。

"dataDeletionDetectionPolicy"": {
    "@odata.type" : "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
    "softDeleteColumnName" : "the property that specifies whether a document was deleted",
    "softDeleteMarkerValue" : "the value that identifies a document as deleted"
}

カスタム クエリを使用している場合、softDeleteColumnName で参照されるプロパティがクエリによってプロジェクションされていることを確認してください。

softDeleteColumnName はインデックス内の最上位のフィールドである必要があります。 複合データ型内での入れ子になったフィールドを softDeleteColumnName として使用することはサポートされていません。

次の例では、ソフト削除ポリシーとともにデータ ソースを作成します。

POST https://[service name].search.windows.net/datasources?api-version=2023-11-01
Content-Type: application/json
api-key: [Search service admin key]

{
    "name": "[my-cosmosdb-ds]",
    "type": "cosmosdb",
    "credentials": {
        "connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.com;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]"
    },
    "container": { "name": "[my-cosmos-collection]" },
    "dataChangeDetectionPolicy": {
        "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
        "highWaterMarkColumnName": "_ts"
    },
    "dataDeletionDetectionPolicy": {
        "@odata.type": "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
        "softDeleteColumnName": "isDeleted",
        "softDeleteMarkerValue": "true"
    }
}

.NET の使用

SQL API プロトコルを介してアクセスされるデータの場合、.NET SDK を使用してインデクサーで自動化することができます。 これまでの REST API セクションを確認し、概念、ワークフロー、要件を理解することをお勧めします。 その後、次の .NET API リファレンス ドキュメントを参照して、マネージド コードで JSON インデクサーを実装できます。

次のステップ

これで、インデクサーの実行状態の監視インデクサーの実行のスケジュール設定をどのように行うか制御できるようになりました。 次の記事は、Azure Cosmos DB からコンテンツをプルするインデクサーに適用されます。