チュートリアル: Azure Storage から入れ子になった JSON BLOB のインデックスを REST を使用して作成する

Azure AI 検索は、Azure ポータルREST APIおよびAzure SDKから使用できます。 また、Foundry IQ は、エンタープライズ コンテンツを、Microsoft Foundry ポータルのエージェントの再利用可能なアクセス許可に対応したナレッジ ベースに変換するマネージド ナレッジ レイヤーです。

Azure AI 検索 は、半構造化データの読み取り方法を解しているインデクサーを使用して、Azure Blob Storage に格納されている JSON のドキュメントや配列のインデックスを作成することができます。 半構造化データには、データ内のコンテンツを分離するタグまたはマーキングが含まれています。 これは、全体にインデックスを付ける必要がある非構造化データと、フィールドごとにインデックス付け可能でリレーショナル データベース スキーマなどのデータ モデルに準拠した正式な構造化データの違いを分割するものです。

このチュートリアルでは、入れ子になった JSON 配列のインデックスを作成し、REST クライアントと 検索 REST API を 使用して次の操作を行う方法について説明します。

  • サンプル データを設定し、azureblob データ ソースを構成する
  • 検索可能なコンテンツを格納する Azure AI 検索 インデックスを作成する
  • インデクサーを作成して実行してコンテナーを読み取り、検索可能なコンテンツを抽出する
  • 作成したインデックスを検索する

前提条件

このチュートリアルには無料の検索サービスを使用できます。 Free レベルでは、3 つのインデックス、3 つのインデクサー、3 つのデータ ソースに制限されます。 このチュートリアルでは、それぞれ 1 つずつ作成します。 開始する前に、サービスで新しいリソースを受け入れる余裕があることを確認します。

ファイルのダウンロード

サンプル データ リポジトリの zip ファイルをダウンロードし、内容を抽出します。 方法については、こちらをご覧ください。

サンプル データは、JSON 配列と 1,521 個の入れ子になった JSON 要素を含む単一の JSON ファイルです。 このデータは、Kaggle の NY フィルハーモニーパフォーマンス履歴 に由来します。 Free レベルのストレージ制限の下に留まる 1 つの JSON ファイルを選択しました。

ファイル内の最初の入れ子になった JSON を次に示します。 ファイルの残りの部分には、コンサート公演の他の 1,520 のインスタンスが含まれています。

    {
      "id": "7358870b-65c8-43d5-ab56-514bde52db88-0.1",
      "programID": "11640",
      "orchestra": "New York Philharmonic",
      "season": "2011-12",
      "concerts": [
        {
          "eventType": "Non-Subscription",
          "Location": "Manhattan, NY",
          "Venue": "Avery Fisher Hall",
          "Date": "2011-09-07T04:00:00Z",
          "Time": "7:30PM"
        },
        {
          "eventType": "Non-Subscription",
          "Location": "Manhattan, NY",
          "Venue": "Avery Fisher Hall",
          "Date": "2011-09-08T04:00:00Z",
          "Time": "7:30PM"
        }
      ],
      "works": [
        {
          "ID": "5733*",
          "composerName": "Bernstein,  Leonard",
          "workTitle": "WEST SIDE STORY (WITH FILM)",
          "conductorName": "Newman, David",
          "soloists": []
        },
        {
          "ID": "0*",
          "interval": "Intermission",
          "soloists": []
        }
      ]
    }

サンプル データを Azure Storage にアップロードする

  1. Azure Storage で、ny-philharmonic-free という名前の新しいコンテナーを作成します。

  2. サンプル データ ファイルのアップロード

  3. Azure AI 検索で接続を作成できるように、ストレージ接続文字列を取得します。

    1. 左側で、[アクセス キー] を選びます。

    2. キー 1 またはキー 2 の接続文字列をコピーします。 接続文字列は、次の例のような URL です:

      DefaultEndpointsProtocol=https;AccountName=<your account name>;AccountKey=<your account key>;EndpointSuffix=core.windows.net
      

検索サービスの URL と API キーをコピーする

このチュートリアルでは、Azure AI 検索への接続にエンドポイントと API キーが必要です。 これらの値は Azure portal から取得できます。 別の接続方法については、「 マネージド ID」を参照してください。

  1. Azure portal で、Search サービスに移動します。

  2. 左側のウィンドウで [ 概要 ] を選択し、エンドポイントをコピーします。 次の形式にする必要があります。 https://my-service.search.windows.net

  3. 左側のウィンドウで [設定]>[キー ]を選択し、サービスに対する完全な権限の管理キーをコピーします。 1 つをロールオーバーする必要がある場合に備えて、ビジネス継続性のために提供される 2 つの交換可能な管理キーがあります。 要求でいずれかのキーを使用して、オブジェクトの追加、変更、または削除を行うことができます。

    Azure portal の URL キーと API キーのスクリーンショット。

REST ファイルを設定する

  1. Visual Studio Code を起動して、新しいファイルを作成します。

  2. 要求で使用される変数の値を指定します。

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE
    @storageConnection = PUT-YOUR-STORAGE-CONNECTION-STRING-HERE
    @blobContainer = PUT-YOUR-CONTAINER-NAME-HERE
    
  3. ファイル拡張子 .rest または .http を使用してファイルを保存します。

REST クライアントのヘルプについては、「 クイック スタート: REST を使用したフルテキスト検索」を参照してください。

データ ソースを作成する

データ ソースの作成 (REST) では、インデックスを付けるデータを指定するデータ ソース接続を作成します。

### Create a data source
POST {{baseUrl}}/datasources?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}

    {
        "name" : "ny-philharmonic-ds",
        "description": null,
        "type": "azureblob",
        "subtype": null,
        "credentials": {
            "connectionString": "{{storageConnection}}"
        },
        "container": {
            "name": "{{blobContainer}}",
            "query": null
        },
        "dataChangeDetectionPolicy": null,
        "dataDeletionDetectionPolicy": null
    }

要求を送信します。 応答は次のようになります。

HTTP/1.1 201 Created
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
ETag: "0x8DC43A5FDB8448F"
Location: https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net:443/datasources('ny-philharmonic-ds')?api-version=2026-04-01
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: 7ca53f73-1054-4959-bc1f-616148a9c74a
elapsed-time: 111
Date: Wed, 13 Mar 2024 21:38:58 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/$metadata#datasources/$entity",
  "@odata.etag": "\"0x8DC43A5FDB8448F\"",
  "name": "ny-philharmonic-ds",
  "description": null,
  "type": "azureblob",
  "subtype": null,
  "credentials": {
    "connectionString": null
  },
  "container": {
    "name": "ny-philharmonic-free",
    "query": null
  },
  "dataChangeDetectionPolicy": null,
  "dataDeletionDetectionPolicy": null,
  "encryptionKey": null
}

インデックスを作成する

インデックスの作成 (REST) では、検索サービスに検索インデックスを作成します。 インデックスでは、すべてのパラメーターとその属性を指定します。

入れ子になった JSON の場合、インデックス フィールドはソース フィールドと同じである必要があります。 現在、Azure AI 検索 では入れ子になった JSON へのフィールド マッピングはサポートされていないため、フィールド名とデータ型は完全に一致する必要があります。 次のインデックスは、生コンテンツの JSON 要素に合わせて配置されます。

### Create an index
POST {{baseUrl}}/indexes?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}

    {
      "name": "ny-philharmonic-index",  
      "fields": [
        {"name": "programID", "type": "Edm.String", "key": true, "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
        {"name": "orchestra", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
        {"name": "season", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
        { "name": "concerts", "type": "Collection(Edm.ComplexType)", 
          "fields": [
            { "name": "eventType", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": false, "sortable": false, "facetable": false},
            { "name": "Location", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "Venue", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "Date", "type": "Edm.String", "searchable": false, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "Time", "type": "Edm.String", "searchable": false, "retrievable": true, "filterable": true, "sortable": false, "facetable": true }
          ]
        },
        { "name": "works", "type": "Collection(Edm.ComplexType)", 
          "fields": [
            { "name": "ID", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": false, "sortable": false, "facetable": false},
            { "name": "composerName", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "workTitle", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "conductorName", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true },
            { "name": "soloists", "type": "Collection(Edm.String)", "searchable": true, "retrievable": true, "filterable": true, "sortable": false, "facetable": true }
          ]
        }
      ]
    }

重要なポイント:

  • フィールド マッピングを使用して、フィールド名またはデータ型の違いを調整することはできません。 このインデックス スキーマは、生のコンテンツをミラーリングするように設計されています。

  • 入れ子になった JSON は、Collection(Edm.ComplextType) としてモデル化されます。 生コンテンツでは、季節ごとに複数のコンサートがあり、各コンサートに複数の作品があります。 この構造体に対応するには、複合型のコレクションを使用します。

  • 生コンテンツでは、DateTime は文字列であるため、インデックス内の対応するデータ型も文字列になります。

インデクサーの作成と実行

インデクサーの作成では、検索サービスにインデクサーを作成します。 インデクサーではデータ ソースに接続し、インデックス データを読み込み、データ更新を自動化するスケジュールを必要に応じて提供します。

インデクサーの構成には、jsonArray 解析モードと documentRoot が含まれます。

### Create and run an indexer
POST {{baseUrl}}/indexers?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}

    {
      "name" : "ny-philharmonic-indexer",
      "dataSourceName" : "ny-philharmonic-ds",
      "targetIndexName" : "ny-philharmonic-index",
      "parameters" : { 
        "configuration" : { 
          "parsingMode" : "jsonArray", "documentRoot": "/programs"}
        },
      "fieldMappings" : [ 
      ]
    }

重要なポイント:

  • 生コンテンツ ファイルには、1,526 個の入れ子になった JSON 構造を持つ JSON 配列 ("programs") が含まれています。 parsingModejsonArray に設定して、各 BLOB に JSON 配列が含まれていることをインデクサーに通知します。 入れ子になった JSON は 1 レベル下から開始されるため、documentRoot/programs に設定します。

  • インデクサーは数分間実行されます。 インデクサーの実行が完了するまで待ってから、クエリを実行してください。

クエリを実行する

最初のドキュメントが読み込まれたらすぐに、検索を始めることができます。

### Query the index
POST {{baseUrl}}/indexes/ny-philharmonic-index/docs/search?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}
  
  {
    "search": "*",
    "count": true
  }

要求を送信します。 これは、インデックスで取得可能としてマークされているすべてのフィールドとドキュメント数を返す、指定されていないフルテキスト検索クエリです。 応答は次のようになります。

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: a95c4021-f7b4-450b-ba55-596e59ecb6ec
elapsed-time: 106
Date: Wed, 13 Mar 2024 22:09:59 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes('ny-philharmonic-index')/$metadata#docs(*)",
  "@odata.count": 1521,
  "@search.nextPageParameters": {
    "search": "*",
    "count": true,
    "skip": 50
  },
  "value": [
  ],
  "@odata.nextLink": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes/ny-philharmonic-index/docs/search?api-version=2026-04-01"
}

文字列で検索する search パラメーター、結果を少数のフィールドに制限する select パラメーター、検索をさらに絞り込むための filter を追加します。

### Query the index
POST {{baseUrl}}/indexes/ny-philharmonic-index/docs/search?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}
  
  {
    "search": "puccini",
    "count": true,
    "select": "season, concerts/Date, works/composerName, works/workTitle",
    "filter": "season gt '2015-16'"
  }

応答で 2 つのドキュメントが返されます。

フィルター処理のため、論理演算子 (and、or、not) と比較演算子 (eq、ne、gt、lt、ge、le) を使用することもできます。 文字列比較では大文字と小文字が区別されます。 詳細と例については、クエリを作成する方法に関するページを参照してください。

$filter パラメーターは、インデックスの作成時にフィルター可能としてマークされたフィールドでのみ機能します。

リセットして再実行する

インデクサーをリセットして実行履歴をクリアすると、完全な再実行が可能になります。 次の POST 要求はリセット用であり、その後に再実行されます。

### Reset the indexer
POST {{baseUrl}}/indexers/ny-philharmonic-indexer/reset?api-version=2026-04-01  HTTP/1.1
  api-key: {{apiKey}}
### Run the indexer
POST {{baseUrl}}/indexers/ny-philharmonic-indexer/run?api-version=2026-04-01  HTTP/1.1
  api-key: {{apiKey}}
### Check indexer status 
GET {{baseUrl}}/indexers/ny-philharmonic-indexer/status?api-version=2026-04-01  HTTP/1.1
  api-key: {{apiKey}}

リソースをクリーンアップする

所有するサブスクリプションを使用している場合は、プロジェクトの終了時に、不要になったリソースを削除することをお勧めします。 リソースを実行したままにすると、お金がかかる場合があります。 リソースは個別に削除することも、リソース グループを削除してリソースのセット全体を削除することもできます。

Azure portal を使って、インデックス、インデクサー、データ ソースを削除できます。

次のステップ

Azure BLOB インデックス作成の基本を理解したら、Azure Storage の JSON BLOB のインデクサー構成を詳しく見てみましょう。