共用方式為


在 Azure AI 搜尋服務中為 Markdown Blob 和檔案編製索引

備註

這項功能目前處於公開預覽狀態。 此預覽版在沒有服務等級協議的情況下提供,不建議用於生產工作負載。 可能不支援特定功能,或可能已經限制功能。 如需詳細資訊,請參閱 Microsoft Azure 預覽版增補使用條款

在 Azure AI 搜尋服務中,Azure Blob 儲存體、Azure 檔案儲存體和 Microsoft OneLake 的索引器支援 markdown Markdown 檔案的解析模式。 Markdown 檔案可透過兩種方式編制索引:

  • 一對多剖析模式,為每個 Markdown 檔案建立多個搜尋文件
  • 一對一解析模式,為每個 Markdown 檔案建立一個搜索文件。

小提示

在檢閱本文之後,繼續進入教學課程:從 Azure Blob 儲存體搜尋 Markdown 資料

先決條件

  • 支援的資料來源:Azure Blob 儲存體、Azure 檔案儲存體、Microsoft OneLake。

    針對 OneLake,請確定您符合 OneLake 索引器的所有需求

    Azure 儲存體的blob 索引器檔案索引器是支持熱存取層和冷存取層的標準效能(一般用途 v2)實例。

Markdown 剖析模式參數

當您建立或更新索引器時,會在索引器定義中指定剖析模式參數。

POST https://[service name].search.windows.net/indexers?api-version=2025-11-01-preview
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 剖析模式提供下列子模式選項:

剖析模式 子模式 搜尋文件 Description
markdown oneToMany 每個 Blob 多個 (預設值)將 Markdown 分成多個搜尋檔,每個檔都代表 Markdown 檔案的內容(非header) 區段。 除非您想要一對一剖析,否則您可以省略子模式。
markdown oneToOne 每個 Blob 一個 將 Markdown 剖析成一個搜尋檔,其中區段對應至 Markdown 檔案中的特定標頭。

針對 oneToMany 子模式,您應檢閱為一個 Blob 編製索引以產生許多搜尋文件 (部分機器翻譯),以了解 Blob 索引子如何針對從相同 Blob 產生之多個搜尋文件的文件索引鍵去除混淆。

稍後各節會更詳細地描述每個子模式。 如果您不熟悉索引子用戶端和概念,請參閱建立搜尋索引子 (機器翻譯)。 您也應熟悉基本 blob 索引子設定的詳細資料,本文不再重複。

選用的 Markdown 剖析參數

參數會區分大小寫。

參數名稱 允許的值 Description
markdownHeaderDepth h1h2h3h4h5h6(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 時,會包含字串欄位 h1h2h3。 這些欄位會透過在索引中鏡像此結構,或透過格式為/sections/h1sections/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=2025-11-01-preview
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 檔案會在編製索引之後產生三個搜尋檔。 由所提供的 Markdown 文件第一個內容區段所產生的搜尋文件將包含 contentsectionsh1h2 的以下值:

{
  {
    "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.Stringh1_header 類型的 Edm.Stringh2_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": "",
  }
}

使用一對一剖析模式

在一對一剖析模式中,整個 Markdown 檔會編製成單一搜尋檔索引,保留原始內容的階層和結構。 當要編製索引的檔案共用通用結構時,此模式最有用,因此您可以在索引中使用這個通用結構,讓相關字段可供搜尋。

在索引器定義中,將 設定 parsingMode"markdown" ,並使用選擇性 markdownHeaderDepth 參數來定義區塊化的最大標題深度。 如果未指定,它會預設為 h6,並擷取所有可能的標頭深度。

Markdown 會根據標題來被剖析成搜尋文件,其中包含以下內容:

  • document_content:包含完整 Markdown 文字做為單一字串。 此欄位可作為輸入檔的原始表示法。

  • sections:對象的陣列,其中包含 Markdown 檔中區段的階層表示法。 每個區段都會以這個陣列中的物件表示,並以巢狀方式擷取檔的結構,其對應至標頭及其各自的內容。 您可以藉由參考路徑 (例如 /sections/content),透過欄位對應存取這些欄位。 此陣列中的物件具有下列屬性:

    • header_level:字串,表示 Markdown 語法中標頭的層級(h1h2h3等等)。 此欄位有助於瞭解內容的階層和結構。

    • header_name: 包含 Markdown 文件中標題文字的文字串。 此欄位提供區段的標籤或標題。

    • content:字串,包含緊接在標頭後,直到下一個標頭為止的文字內容。 此欄位會擷取與標頭相關聯的詳細資訊或描述。 如果標題正下方沒有內容,則值為空字串。

    • ordinal_position:整數值,表示區段在文件階層中的位置。 用此欄位可以根據文件中的順序排序各段落,從序列位置 1 開始,每個內容區塊順序遞增。

    • sections:陣列,包含表示目前區段下巢狀子區段的物件。 此陣列遵循與最上層 sections 數位相同的結構,允許表示多個巢狀內容層級。 每個子區段物件也包含 header_levelheader_namecontentordinal_position 屬性,啟用遞歸結構,代表 Markdown 內容的階層。

以下是我們用來解釋圍繞每種剖析模式設計的索引結構描述的範例 Markdown。

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

一對一解析的索引模式

如果您未使用欄位對應,索引的形狀應該會反映 Markdown 內容的形狀。 假設範例 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=2025-11-01-preview
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 內容中實際存在的標頭,而不一定包含從h1h6連續的巢狀區段。 例如,當檔案從h2開始時,最上層區段陣列中的第一個元素是h2

在搜尋索引中對應一對一欄位

如果您想要從檔中擷取具有自定義名稱的欄位,您可以使用欄位對應來執行此動作。 使用與之前相同的 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."
}

備註

這些範例會指定如何在使用或不使用欄位對應的情況下完全使用這些剖析模式,但如果它適合您的需要,您可以在一個案例中同時套用這兩種方式。

透過 Markdown 重新編製索引來管理過時的文件

使用一對多重剖析模式時,如果刪除了區段,重新編製修改後的 Markdown 檔案的索引可能會導致文件過時或重複。 此行為是一對多模式特有的,不適用於一對一剖析。

行為概觀

一對多剖析模式

oneToMany 模式下,每個 Markdown 區段 (以標題為基礎) 都會被編入索引,並作為一個個別的搜尋文件。 檔案重新編入索引時:

  • 不會自動刪除:索引子會以新文件覆寫現有文件,但不會刪除與更新後文件內容不再對應的文件。
  • 可能出現重複項:特別只有在刪除的區段多於索引編製執行之間插入的區段時,才會發生此問題。 在這種情況下,先前版本中的剩餘文件會保留在索引中,進而導致過時的項目不再反映來源檔案的目前狀態。

一對一剖析模式

oneToOne 模式下,整個 Markdown 檔案會被編入索引,並作為一個搜尋文件。 檔案重新編入索引時:

  • 覆寫行為:現有文件會被新版本完全取代。
  • 沒有過時的區段:當檔案重新編入索引時,現有文件會被更新版本取代,已移除的內容將不再包含在內。 唯一的例外是檔案路徑或 Blob URI 變更,這可能會導致在舊文件旁邊建立新文件。

因應措施選項

若要確保索引反映 Markdown 檔案的目前狀態,請考慮下列其中一種方法:

選項 1。 具有中繼資料的虛刪除

此方法會使用虛刪除來刪除與特定 Blob 相關聯的文件。 如需詳細資訊,請參閱在 Azure AI 搜尋服務中使用 Azure 儲存體的索引子進行變更和刪除偵測 (部分機器翻譯)。

步驟:

  1. 設定中繼資料欄位,以將 Blob 標記為已刪除。
  2. 讓索引子執行。 它會刪除索引中與該 Blob 相關聯的所有文件。
  3. 移除虛刪除標記,然後重新編製檔案的索引。

選項 2。 使用 delete API

在重新編製修改後的 Markdown 檔案的索引之前,請使用 delete API 明確刪除與該檔案相關聯的現有文件。 您可以選擇以下其中一項:

  • 手動辨識過時文件,透過識別索引中重複的檔案來刪除。 這對於小規模且易於理解的變更可能是可行的,但可能會耗時。
  • (建議) 在重新編製索引之前,移除從同一個父檔案中產生的所有文件,以確保避免不一致。

步驟:

  1. 識別與檔案相關聯之文件的識別碼。 使用類似以下範例的查詢來擷取與特定檔案相關聯的所有文件的文件索引鍵識別碼 (例如 idchunk_id 等)。 將 metadata_storage_path 取代為索引中對應到檔案路徑或 Blob URI 的相應欄位。 此欄位必須是索引鍵。

    GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2025-05-01-preview
    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=2025-05-01-preview
    Content-Type: application/json
    api-key: [admin key]
    
    {  
      "value": [  
        {  
          "@search.action": "delete",  
          "id": "aHR0c...jI1"  
        },
        {  
          "@search.action": "delete",  
          "id": "aHR0...MQ2"  
        }  
      ]  
    }
    
  3. 重新編製已更新檔案的索引。

後續步驟