Azure AI 検索内の Markdown BLOB とファイルのインデックスを作成する

メモ

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

Important

これらの機能は、他のMicrosoft サービスおよびサード パーティのサービスへの接続をサポートします。 これらのサービスの利用は各サービスの利用規約に従うものとし、データが Azure コンプライアンス境界の外部で処理または保存されたり、Azure コンプライアンス境界内に流入したりする場合があります。

データが組織のコンプライアンスと地理的境界の外部に流れるかどうか、および関連する影響、および適切なアクセス許可、境界、承認がプロビジョニングされるかどうかを管理するのは、お客様の責任です。

特定のユース ケースのコンテキストで構築したアプリケーションを慎重に確認およびテストし、すべての適切な決定とカスタマイズを行う責任があります。 これには、メタプロンプト、コンテンツ フィルター、その他の安全システムなどの独自の責任ある AI 軽減策の実装や、アプリケーションが適切な品質、信頼性、セキュリティ、信頼性の標準を満たしていることを確認する機能が含まれます。 詳細については、「Azure AI 検索透過性に関するメモを参照してください。

Azure AI 検索では、Azure Blob Storage、Azure Files、および Microsoft OneLake のインデクサーは、Markdown ファイルの markdown 解析モードをサポートします。 Markdown ファイルは、次の 2 つの方法でインデックスを作成できます。

  • 1 対多の解析モード。Markdown ファイルごとに複数の検索ドキュメントが作成されます。
  • 1 対 1 の解析モード。Markdown ファイルごとに 1 つの検索ドキュメントが作成されます。

ヒント

この記事を確認したら、「Tutorial: Azure Blob Storageに進みます。

前提 条件

Markdown 解析モードのパラメーター

解析モードのパラメーターは、インデクサーの作成時または更新時にインデクサー定義で指定されます。

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToMany",
      "markdownHeaderDepth": "h6"
    }
  },
}

BLOB インデクサーは、検索ドキュメントの出力構造を決定するための submode パラメーターを提供します。 Markdown 解析モードには、次のサブモード オプションがあります。

解析モード サブモード ドキュメントの検索 説明
markdown oneToMany BLOB ごとに複数 (既定値)Markdown を複数の検索ドキュメントに分割し、それぞれ Markdown ファイルのコンテンツ (非ヘッダー) セクションを表します。 1 対 1 の解析が必要な場合を除き、サブモードを省略できます。
markdown oneToOne BLOB ごとに 1 つ Markdown ファイル内の特定のヘッダーにマップされたセクションを使用して、Markdown を 1 つの検索ドキュメントに解析します。

oneToManyサブモードの場合は、1つのBLOBをインデックス化して多数の検索ドキュメントを生成することを確認し、同じBLOBから生成された複数の検索ドキュメントにおけるドキュメントキーの曖昧さをBLOBインデクサーがどのように解消するかを理解する必要があります。

以降のセクションでは、各サブモードについて詳しく説明します。 インデクサークライアントと概念に慣れていない場合は、「 検索インデクサーを作成する」を参照してください。 また、ここでは繰り返されない 基本的な BLOB インデクサー構成の詳細についても理解しておく必要があります。

オプションの Markdown 解析パラメーター

パラメータは大文字・小文字を区別します。

パラメーター名 使用できる値 説明
markdownHeaderDepth h1、 h2、 h3、 h4、 h5、 h6 (default) このパラメーターは、解析時に考慮される最も深いヘッダー レベルを決定し、ドキュメント構造の柔軟な処理を可能にします (たとえば、 markdownHeaderDepth が h1 に設定されている場合、パーサーは "#" で始まる最上位ヘッダーのみを認識し、下位レベルのすべてのヘッダーはプレーン テキストとして扱われます)。 指定しない場合、既定値は h6 になります。

この設定は、インデクサーの作成後に変更できます。 ただし、結果として得られる検索ドキュメントの構造は、Markdown コンテンツによって変わる場合があります。

サポートされている Markdown 要素

Markdown 解析では、ヘッダーに基づいてコンテンツのみが分割されます。 リスト、コード ブロック、テーブルなどの他のすべての要素は、プレーン テキストとして扱われ、コンテンツ フィールドに渡されます。

Markdown コンテンツのサンプル

このページの例では、次の Markdown コンテンツが使用されています。

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

一対多解析モードを使用する

一対多解析モードでは、Markdown ファイルが複数の検索ドキュメントに解析されます。各ドキュメントは、ドキュメント内のヘッダー メタデータに基づいて Markdown ファイルの特定のコンテンツ セクションに対応します。 Markdown は、ヘッダーに基づいて検索ドキュメントに解析され、次の内容が含まれます。

  • content: ドキュメント内のその時点のヘッダー メタデータに基づいて、特定の場所で見つかった未加工の Markdown を含む文字列。

  • sections: 目的のヘッダー レベルまでのヘッダー メタデータのサブフィールドを含むオブジェクト。 たとえば、 markdownHeaderDepth が h3に設定されている場合は、文字列フィールド h1、 h2、および h3が含まれます。 これらのフィールドは、インデックス内のこの構造をミラーリングするか、 /sections/h1、 /sections/h2などの形式でフィールド マッピングを使用してインデックスを作成します。 コンテキスト内の例については、次のサンプルのインデックスとインデクサーの構成を参照してください。 含まれるサブフィールドは次のとおりです。

    • h1 - h1 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
    • (省略可能) h2- h2 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
    • (省略可能) h3- h3 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
    • (省略可能) h4- h4 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
    • (省略可能) h5- h5 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
    • (省略可能) h6- h6 ヘッダー値を含む文字列。 ドキュメントのこの時点で設定されていない場合は空の文字列。
  • ordinal_position: ドキュメント階層内のセクションの位置を示す整数値。 このフィールドは、元の順序でセクションを並べ替える際に使用されます。最初は序数が 1 で始まり、ヘッダーごとに順番にインクリメントされます。

一対多解析のインデックス スキーマ

インデックス構成の例は、次のようになります。

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "content",
    "type": "Edm.String",
  },
  {
    "name": "ordinal_position",
    "type": "Edm.Int32"
  },
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "h1",
      "type": "Edm.String"
    },
    {
      "name": "h2",
      "type": "Edm.String"
    }]
  }]
}

一対多解析のインデクサー定義

フィールド名とデータ型が一致する場合、BLOB インデクサーは、要求に明示的なフィールド マッピングが存在しないマッピングを推論できるため、指定されたインデックス構成に対応するインデクサー構成は次のようになります。

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": { "parsingMode": "markdown" }
  },
}

メモ

submodeが既定であるため、ここでoneToManyを明示的に設定する必要はありません。

一対多解析のインデクサー出力

この Markdown ファイルでは、3 つのコンテンツ セクションが原因で、インデックス作成後に 3 つの検索ドキュメントが生成されます。 指定された Markdown ドキュメントの最初のコンテンツ セクションの結果の検索ドキュメントには、 content、 sections、 h1、および h2の次の値が含まれます。

{
  {
    "content": "Content for section 1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": ""
    },
    "ordinal_position": 1
  },
  {
    "content": "Content for subsection 1.1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": "Subsection 1.1"
    },
    "ordinal_position": 2
  },
  {
    "content": "Content for section 2.\r\n",
    "sections": {
      "h1": "Section 2",
      "h2": ""
    },
    "ordinal_position": 3
  }
}

検索インデックス内の一対多フィールドをマップする

フィールド マッピングは、フィールド名と型が同一でない場合に、ソース フィールドを変換先フィールドに関連付けます。 ただし、フィールド マッピングを使用して Markdown ドキュメントの一部を照合し、検索ドキュメントの最上位フィールドに "リフト" することもできます。

このシナリオの例を次に示します。 一般的なフィールド マッピングの詳細については、 フィールド マッピングを参照してください。

raw_content型のEdm.String、h1_header型のEdm.String、およびh2_header型のEdm.Stringを含む検索インデックスを想定します。 Markdown を目的の図形にマップするには、次のフィールド マッピングを使用します。

"fieldMappings" : [
    { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
    { "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
    { "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
  ]

インデックス内の結果の検索ドキュメントは次のようになります。

{
  {
    "raw_content": "Content for section 1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "",
  },
  {
    "raw_content": "Content for section 1.1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "Subsection 1.1",
  },
  {
    "raw_content": "Content for section 2.\r\n",
    "h1_header": "Section 2",
    "h2_header": "",
  }
}

1 対 1 の解析モードを使用する

1 対 1 の解析モードでは、Markdown ドキュメント全体に 1 つの検索ドキュメントとしてインデックスが作成され、元のコンテンツの階層と構造が保持されます。 このモードは、インデックスを作成するファイルが共通の構造を共有している場合に最も便利です。これにより、インデックス内のこの共通構造を使用して、関連するフィールドを検索可能にすることができます。

インデクサー定義内で、 parsingMode を "markdown" に設定し、省略可能な markdownHeaderDepth パラメーターを使用してチャンクの最大見出し深度を定義します。 指定がない場合は、h6 が既定値となり、すべてのヘッダーの深さを取得します。

Markdown は、ヘッダーに基づいて検索ドキュメントに解析され、次の内容が含まれます。

  • document_content: Markdown テキスト全体を 1 つの文字列として格納します。 このフィールドは、入力ドキュメントの生の表現として機能します。

  • sections: Markdown ドキュメント内のセクションの階層表現を含むオブジェクトの配列。 各セクションはこの配列内のオブジェクトとして表され、ヘッダーとそれぞれのコンテンツに対応する入れ子になった方法でドキュメントの構造をキャプチャします。 フィールドには、パスを参照することでフィールド マッピングを介してアクセスできます (たとえば、 /sections/content)。 この配列内のオブジェクトには、次のプロパティがあります。

    • header_level: Markdown 構文のヘッダーのレベル (h1、 h2、 h3など) を示す文字列。 このフィールドは、コンテンツの階層と構造を理解するのに役立ちます。

    • header_name: Markdown ドキュメントに表示されるヘッダーのテキストを含む文字列。 このフィールドには、セクションのラベルまたはタイトルが表示されます。

    • content: ヘッダーの直後の次のヘッダーまでのテキスト コンテンツを含む文字列。 このフィールドは、ヘッダーに関連付けられている詳細情報または説明をキャプチャします。 ヘッダーのすぐ下にコンテンツがない場合、値は空の文字列です。

    • ordinal_position: ドキュメント階層内のセクションの位置を示す整数値。 このフィールドは、文書に表示される元の順序でセクションを並べ替える場合に使用されます。序数の位置は 1 から始まり、コンテンツ ブロックごとに順番にインクリメントされます。

    • sections: 現在のセクションの下に入れ子になったサブセクションを表すオブジェクトを含む配列。 この配列は、最上位レベルの sections 配列と同じ構造に従い、複数レベルの入れ子になったコンテンツを表現できます。 各サブセクション オブジェクトには、 header_level、 header_name、 content、および ordinal_position プロパティも含まれており、Markdown コンテンツの階層を表す再帰構造が可能になります。

各解析モードを中心に設計されたインデックス スキーマを説明するために使用しているサンプル Markdown を次に示します。

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

1 対 1 の解析のインデックス スキーマ

フィールド マッピングを使用しない場合、インデックスの図形は Markdown コンテンツの形状を反映している必要があります。 2 つのセクションと 1 つのサブセクションを含むサンプル Markdown の構造を考えると、インデックスは次の例のようになります。

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "document_content",
    "type": "Edm.String"
  },
  {
    "name": "sections",
    "type": "Collection(Edm.ComplexType)",
    "fields": [
    {
      "name": "header_level",
      "type": "Edm.String"
    },
    {
      "name": "header_name",
      "type": "Edm.String"
    },
    {
      "name": "content",
      "type": "Edm.String"
    },
    {
      "name": "ordinal_position",
      "type": "Edm.Int32"
    },
    {
      "name": "sections",
      "type": "Collection(Edm.ComplexType)",
      "fields": [
      {
        "name": "header_level",
        "type": "Edm.String"
      },
      {
        "name": "header_name",
        "type": "Edm.String"
      },
      {
        "name": "content",
        "type": "Edm.String"
      },
      {
        "name": "ordinal_position",
        "type": "Edm.Int32"
      }]
    }]
  }]
}

一対一解析のインデクサー定義

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToOne",
    }
  }
}

一対一解析のインデクサー出力

インデックスを作成する Markdown は h2 の深さ ("##") にのみ移動するため、 sections フィールドを深さ 2 に入れ子にして一致させる必要があります。 この構成では、インデックスに次のデータが含まれます。

  "document_content": "# Section 1\r\nContent for section 1.\r\n## Subsection 1.1\r\nContent for subsection 1.1.\r\n# Section 2\r\nContent for section 2.\r\n",
  "sections": [
    {
      "header_level": "h1",
      "header_name": "Section 1",
      "content": "Content for section 1.",
      "ordinal_position": 1,
      "sections": [
        {
          "header_level": "h2",
          "header_name": "Subsection 1.1",
          "content": "Content for subsection 1.1.",
          "ordinal_position": 2,
        }]
    }],
    {
      "header_level": "h1",
      "header_name": "Section 2",
      "content": "Content for section 2.",
      "ordinal_position": 3,
      "sections": []
    }]
  }

ご覧のように、序数の位置は、ドキュメント内のコンテンツの場所に基づいてインクリメントされます。

コンテンツ内でヘッダー レベルがスキップされた場合、結果のドキュメントの構造には Markdown コンテンツに存在するヘッダーが反映され、 h1 から h6までの連続する入れ子になったセクションが含まれているとは限りません。 たとえば、ドキュメントが h2で始まる場合、最上位セクション配列の最初の要素は h2。

検索インデックス内の 1 対 1 のフィールドをマップする

ドキュメントからカスタム名を持つフィールドを抽出するには、フィールド マッピングを使用できます。 前と同じ Markdown サンプルを使用して、次のインデックス構成を検討してください。

{
  "name": "my-markdown-index",
  "fields": [
    {
      "name": "document_content",
      "type": "Edm.String",
    },
    {
      "name": "document_title",
      "type": "Edm.String",
    },
    {
      "name": "opening_subsection_title",
      "type": "Edm.String"
    },
    {
      "name": "summary_content",
      "type": "Edm.String",
    }
  ]
}

解析された Markdown からの特定のフィールドの抽出は、outputFieldMappings でのドキュメント パスと同様に処理されます。ただし、パスは/sectionsではなく /document で始まる点が異なります。 たとえば、 /sections/0/content は、セクション配列の 0 の位置にある項目の下のコンテンツにマップされます。

例えば強力なユースケースの例は、すべての Markdown ファイルの最初の h1 にドキュメントタイトルがあり、最初の h2 にはサブセクションタイトルがあり、最後の h1 の下にある最終段落の内容に要約があります。 次のフィールド マッピングを使用して、そのコンテンツにのみインデックスを作成できます。

"fieldMappings" : [
  { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
  { "sourceFieldName" : "/sections/0/header_name", "targetFieldName" : "document_title" },
  { "sourceFieldName" : "/sections/0/sections/header_name", "targetFieldName" : "opening_subsection_title" },
  { "sourceFieldName" : "/sections/1/content", "targetFieldName" : "summary_content" },
]

ここでは、そのドキュメントから関連する部分のみを抽出します。 この機能を最も効果的に使用するには、インデックスを作成する予定のドキュメントで同じ階層ヘッダー構造を共有する必要があります。

インデックス内の結果の検索ドキュメントは次のようになります。

{
  "content": "Content for section 1.\r\n",
  "document_title": "Section 1",
  "opening_subsection_title": "Subsection 1.1",
  "summary_content": "Content for section 2."
}

メモ

これらの例では、フィールド マッピングの有無にかかわらず、これらの解析モードを完全に使用する方法を指定しますが、ニーズに合わせて 1 つのシナリオで両方を適用できます。

Markdown のインデックス再作成から古いドキュメントを管理する

一対多解析モードを使用する場合、変更された Markdown ファイルのインデックスを再作成すると、セクションが削除されると、古いドキュメントまたは重複するドキュメントが発生する可能性があります。 この動作は一対多モードに固有であり、1 対 1 の解析には適用されません。

動作の概要

一対多解析モード

oneToMany モードでは、(ヘッダーに基づいて) 各 Markdown セクションに個別の検索ドキュメントとしてインデックスが付けられます。 ファイルのインデックスを再作成する場合:

  • 自動削除なし: インデクサーは既存のドキュメントを新しいドキュメントで上書きしますが、更新されたファイル内のコンテンツに対応しなくなったドキュメントは削除されません。
  • 重複の可能性: この問題は、インデックス作成の実行間に挿入されたセクションよりも多くのセクションが削除された場合にのみ発生します。 このような場合、以前のバージョンの残ったドキュメントはインデックスに残り、ソース ファイルの現在の状態を反映しない古いエントリが発生します。

1 対 1 の解析モード

oneToOne モードでは、Markdown ファイル全体に 1 つの検索ドキュメントとしてインデックスが作成されます。 ファイルのインデックスを再作成する場合:

  • 上書き動作: 既存のドキュメントは、完全に新しいバージョンに置き換えられます。
  • 古いセクションなし: ファイルのインデックスが再作成されると、既存のドキュメントは更新バージョンに置き換えられ、削除されたコンテンツは含まれません。 唯一の例外は、ファイル パスまたは BLOB URI が変更された場合であり、古いドキュメントと共に新しいドキュメントが作成される可能性があります。

回避策のオプション

インデックスに Markdown ファイルの現在の状態が反映されるようにするには、次のいずれかの方法を検討してください。

オプション 1。 メタデータを使用した論理的な削除

このメソッドでは、特定の BLOB に関連するドキュメントをソフト削除によって削除します。 詳細については、「 Azure AI 検索 のAzure Storageにインデクサーを使用した変更と削除の検出」を参照してください。

手順:

  1. メタデータ フィールドを設定して、BLOB を削除済みとしてマークします。
  2. インデクサーを実行します。 その BLOB に関連付けられているインデックス内のすべてのドキュメントが削除されます。
  3. ソフト削除マーカーを取り除き、ファイルを再インデックスします。

オプション 2。 削除 API を使用する

変更した Markdown ファイルのインデックスを再作成する前に、delete API を使用して、そのファイルに関連付けられている既存のドキュメントを明示的に 削除します。 次のいずれかを実行できます。

  • 削除するインデックス内の重複を識別して、個々の古いドキュメントを手動で識別します。 これは、小規模で十分に理解された変更に対して実現可能な場合がありますが、時間がかかる場合があります。
  • (推奨)インデックスを再作成する前に、同じ親ファイルから生成されたすべてのドキュメントを削除して、不整合を回避します。

手順:

  1. ファイルに関連付けられているドキュメントの ID を識別します。 次の例のようなクエリを使用して、特定のファイルに関連付けられているすべてのドキュメントのドキュメント キー ID ( id や chunk_idなど) を取得します。 metadata_storage_pathを、ファイル パスまたは BLOB URI にマップするインデックス内の適切なフィールドに置き換えます。 このフィールドはキーである必要があります。

    GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    
      {
          "filter": "metadata_storage_path eq 'https://<storage-account>.blob.core.windows.net/<container-name>/<file-name>.md'",
          "select": "id"
      }
    
  2. 識別されたキーを持つドキュメントの削除要求を発行します。

    POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    {
      "value": [
        {
          "@search.action": "delete",
          "id": "aHR0c...jI1"
        },
        {
          "@search.action": "delete",
          "id": "aHR0...MQ2"
        }
      ]
    }
    
  3. 更新されたファイルのインデックスを再作成します。

次の手順