更新或重建 Azure AI 搜尋服務 中的索引

註

Azure AI 搜尋服務 可透過 Azure 入口網站、REST API 及 Azure SDK 取得。 它同時也是 Foundry IQ 的基礎,這是一個管理式知識層,能將企業內容轉化為可重複使用、權限感知的知識庫,供 Microsoft Foundry 入口網站中的代理使用。

本文說明如何在 Azure AI 搜尋服務 中透過增量索引來更新現有索引,並進行結構變更或內容變更。

提示

要立即更新文件,請跳到 「更新內容」。 關於結構變更,請參見 更新索引架構。

先決條件

提示

在開發過程中,當反覆調整索引設計時,常常會捨棄並重建索引。 使用少數具代表性的資料樣本,讓重新索引更快。 對於生產架構的變更,請建立並並排測試一個新的索引,然後使用 索引別名 交換索引,而不更改應用程式代碼。

更新內容

增量索引與索引與來源資料變化同步是大多數搜尋應用的基本功能。 本節說明透過 REST API 新增、移除或覆寫搜尋索引內容的工作流程,但 Azure SDK 提供相當的功能。

請求正文包含一份或多份需索引的文件。 在請求中,索引中的每份文件如下:

  • 以獨特的大小寫區分鍵標示。
  • 與一個動作相關:「上傳」、「刪除」、「合併」或「合併或上傳」。
  • 填入一組名稱/值配對,用於您要新增或更新的每個欄位。
{  
  "value": [  
    {  
      "@search.action": "upload (default) | merge | mergeOrUpload | delete",  
      "key_field_name": "unique_key_of_document", (key/value pair for key field from index schema)  
      "field_name": field_value (name/value pairs matching index schema)  
        ...  
    },  
    ...  
  ]  
}

參考資料:文件 - 索引

  • 首先,使用載入文件的 API,例如 Documents - 索引(REST)或Azure SDK中等效的 API。 欲了解更多索引技術資訊,請參閱 載入文件。

  • 對於大型更新,建議使用批次處理(每批次最多 1,000 份文件,或約 16 MB,以先到者為準)來大幅提升索引效能。

  • 在 API 上設定 @search.action 參數,以判斷對現有文件的影響。 用於 mergeOrUpload 增量更新(最常見的)、 delete 移除文件,或 merge 部分欄位更新現有文件。

    行動 影響
    刪除 將整份文件從索引中移除。 如果你想移除單一欄位,請改用合併,並將該欄位設為 null。 刪除的文件和欄位並不會立刻釋放索引空間。 每隔幾分鐘,背景程序會執行物理刪除。 無論你是使用 Azure 入口網站還是 API 來回傳索引統計,刪除結果在 Azure 入口網站及 API 中反映前,都可以預期會有一點延遲。 欲了解更多資訊,請參閱 搜尋索引中的刪除文件。
    合併 更新已存在的文件,並讓找不到的文件失敗。 合併會替換現有的值。 因此,務必檢查那些包含多個值的集合欄位,例如類型為 Collection(Edm.String) 的欄位。 例如,若一個 tags 欄位以 ["budget"] 開始,並執行與 ["economy", "pool"] 的合併,該 tags 欄位的最終值為 ["economy", "pool"]。 它不會是 ["budget", "economy", "pool"]。

    同樣的行為也適用於複雜的集合。 若文件包含一個名為 Rooms 的複雜集合欄位,值為 [{ "Type": "Budget Room", "BaseRate": 75.0 }],且你執行值為 [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]的合併,Rooms 欄位的最終值將為 [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]。 它不會新增或合併新舊值。
    合併或上傳 如果文件存在,則會進行合併;如果文件是新的,則會上傳。 這是最常見的增量更新操作。
    上傳 類似於一種名為「upsert」的操作:如果文件是新的,則插入;如果文件已存在,則更新或替換。 如果文件缺少索引所需的值,則文件欄位的值會設為 null。

編製索引期間查詢會繼續執行,但如果您正在更新或移除現有欄位,可能會看到混合結果,且節流發生率較高。

註

請求體中哪個動作先執行,沒有順序上的保證。 不建議在同一個請求主體中對同一份文件進行多個「合併」操作。 如果同一文件需要多個「合併」操作,請先在客戶端執行合併,再更新搜尋索引中的文件。

回應

成功回應會回傳狀態碼 200,表示所有項目都已永久儲存,將開始被索引。 索引會在背景執行,並在索引操作完成後幾秒內,讓新文件可用(也就是可查詢和搜尋)。 具體的延遲取決於服務負載。

當索引成功時,所有項目的狀態屬性均設為 true,且 statusCode 屬性設為 201(針對新上傳的文件)或 200(針對合併或刪除的文件):

{
  "value": [
    {
      "key": "unique_key_of_new_document",
      "status": true,
      "errorMessage": null,
      "statusCode": 201
    },
    {
      "key": "unique_key_of_merged_document",
      "status": true,
      "errorMessage": null,
      "statusCode": 200
    },
    {
      "key": "unique_key_of_deleted_document",
      "status": true,
      "errorMessage": null,
      "statusCode": 200
    }
  ]
}

當至少有一個項目未成功索引時,狀態代碼 207 會被回傳。 尚未被索引的項目狀態欄位會被設定為 false。 errorMessage和 statusCode 性質表示索引錯誤的原因:

{
  "value": [
    {
      "key": "unique_key_of_document_1",
      "status": false,
      "errorMessage": "The search service is too busy to process this document. Please try again later.",
      "statusCode": 503
    },
    {
      "key": "unique_key_of_document_2",
      "status": false,
      "errorMessage": "Document not found.",
      "statusCode": 404
    },
    {
      "key": "unique_key_of_document_3",
      "status": false,
      "errorMessage": "Index is temporarily unavailable because it was updated with the 'allowIndexDowntime' flag set to 'true'. Please try again later.",
      "statusCode": 422
    }
  ]
}  

errorMessage該性質表示索引錯誤的原因(如可能)。

下表說明了可在回應中回傳的各種文件狀態碼。 有些狀態碼表示請求本身有問題,而有些則表示暫時錯誤狀況。 後者你應該在延遲後再試一次。

狀態代碼 意義 可重試 註釋
200 文件已成功修改或刪除。 無 刪除作業為等冪。 也就是說,即使索引中不存在文件鍵,嘗試用該鍵進行刪除操作仍會導致 200 的狀態碼。
201 文件已成功建立。 無
400 文件中有一個錯誤,導致無法被索引。 不 回應中的錯誤訊息指出文件的問題所在。
404 文件無法合併,因為給定的金鑰不存在於索引中。 不 上傳不會發生這個錯誤,因為它們會建立新文件;刪除則不會發生,因為它們是冪等元的。
409 嘗試索引文件時偵測到版本衝突。 是的 這種情況可能發生在你同時嘗試多次索引同一份文件時。
422 索引暫時無法使用,因為它更新時將「allowIndexDowntime」標誌設為「true」。 是的
429 太多請求 是的 如果你在索引時出現這個錯誤代碼,通常代表你的儲存空間快用完了。 當你接近 儲存空間限制時,服務可能會進入一個狀態,必須刪除部分文件才能新增或更新。 欲了解更多資訊,請參閱 「規劃與管理容量 」,若你想要更多儲存空間,或透過刪除文件釋放空間。
503 您的搜尋服務暫時無法使用,可能是因為負載過重。 是的 在這種情況下,你的程式碼應該先等一等再重試,否則可能會延長服務無法使用的時間。

如果你的客戶端程式碼經常遇到 207 回應,一個可能的原因是系統正處於負載狀態。 你可以透過查看 503 的 statusCode 屬性來確認。 如果狀態代碼是 503,我們建議限制索引請求。 否則,如果索引流量沒有減少,系統可能會開始以 503 錯誤拒絕所有請求。

狀態代碼 429 表示您已超過每個索引文件數量的配額。 你必須 升級以達到更高的容量上限 ,或是建立新的索引。

註

當你將帶有時區資訊的DateTimeOffset值上傳到索引時,Azure AI 搜尋服務會將這些值正規化為UTC。 例如,2024-01-13T14:03:00-08:00 會被儲存為 2024-01-13T22:03:00Z。 如果你需要儲存時區資訊,可以在索引中多加一欄來處理這個資料點。

增量索引的技巧

  • 索引器自動化增量索引。 如果你能使用索引器,且資料來源支援變更追蹤,你可以以定期排程執行索引器,新增、更新或覆寫可搜尋的內容,使其與外部資料同步。

  • 如果您是直接透過 推送 API 進行索引呼叫,請使用 mergeOrUpload 作為搜尋動作。

  • 有效載荷必須包含你想新增、更新或刪除的每份文件的鍵或識別碼。

  • 如果你的索引包含向量欄位,且你將屬性設stored為 false,請確保在部分文件更新中提供向量,即使該值未改變。 將 設 stored 為 false 的副作用是,重新索引操作時會丟棄向量。 在文件有效載荷中提供向量可防止這種情況發生。

  • 要更新複雜型態中簡單欄位和子欄位的內容,請只列出你想更改的欄位。 例如,如果你只需要更新一個描述欄位,有效載荷應該包含文件鍵與修改後的描述。 省略其他欄位則保留其現有數值。

  • 若要將內嵌變更合併成字串集合,請提供整個值。 回想tags在前一部分中的字段範例。 新值會覆蓋整個欄位的舊值,且欄位內容不會合併。

這裡有一個 REST API 範例 ,示範這些技巧:

### Get Stay-Kay City Hotel by ID
GET  {{baseUrl}}/indexes/hotels-vector-quickstart/docs('1')?api-version=2026-04-01  HTTP/1.1
    Content-Type: application/json
    api-key: {{apiKey}}

### Change the description, city, and tags for Stay-Kay City Hotel
POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search.index?api-version=2026-04-01  HTTP/1.1
  Content-Type: application/json
  api-key: {{apiKey}}

    {
        "value": [
            {
            "@search.action": "mergeOrUpload",
            "HotelId": "1",
            "Description": "I'm overwriting the description for Stay-Kay City Hotel.",
            "Tags": ["my old item", "my new item"],
            "Address": {
                "City": "Gotham City"
                }
            }
        ]
    }
       
### Retrieve the same document, confirm the overwrites and retention of all other values
GET  {{baseUrl}}/indexes/hotels-vector-quickstart/docs('1')?api-version=2026-04-01  HTTP/1.1
    Content-Type: application/json
    api-key: {{apiKey}}

參考文獻:文件 - 索引、 查詢文件

SDK 範例

以下範例展示了如何使用 Azure SDK 更新文件。

from azure.core.credentials import AzureKeyCredential
from azure.search.documents import SearchClient

# Set up the client
service_name = "<your-search-service-name>"
index_name = "hotels-sample"
api_key = "<your-admin-api-key>"

endpoint = f"https://{service_name}.search.windows.net"
credential = AzureKeyCredential(api_key)
client = SearchClient(endpoint=endpoint, index_name=index_name, credential=credential)

# Update documents using merge_or_upload
documents = [
    {
        "HotelId": "1",
        "Description": "Updated description for the hotel.",
        "Tags": ["updated", "renovated"]
    }
]

result = client.merge_or_upload_documents(documents=documents)
print(f"Updated {len(result)} document(s)")

參考資料:SearchClient,merge_or_upload_documents

更新索引結構

索引結構定義了搜尋服務中建立的實體資料結構,因此你無法做太多結構變更,除非需要完全重建。

更新但無需重建

以下列表列舉可無縫導入現有索引的結構變更。 通常,該清單包含查詢執行時使用的新欄位與功能。

  • 新增 索引描述
  • 新增欄位
  • 將屬性設定 retrievable 在現有欄位上
  • 更新已有 searchAnalyzer 之欄位上的 indexAnalyzer
  • 在索引中新增一個分析 器定義 (可套用到新欄位)
  • 新增、更新或刪除 評分檔案
  • 新增、更新或刪除 同義地圖
  • 新增、更新或刪除 語意配置
  • 新增、更新或刪除 CORS 設定

操作順序為:

  1. 取得索引定義。

  2. 用之前清單的更新來修正結構。

  3. 更新搜尋服務的索引架構。

  4. 如果你新增了一個欄位,請更新索引內容以符合你修訂後的架構。 其他所有變更則會使用現有索引內容不做任何修改。

當你更新索引結構以新增欄位時,索引中現有的文件會被賦予該欄位的空值。 在下一個索引工作中,外部來源資料的值會取代 Azure AI 搜尋服務 新增的空值。

更新期間不應有查詢中斷,但查詢結果會隨著更新生效而變化。

需要重建的更新

部分改裝需要刪除並重建現有索引,將現有索引換成新的。

行動 描述
刪除欄位 要實體移除欄位的所有痕跡,你必須重建索引。 當立即重建不切實際時,你可以修改應用程式程式碼,將存取權從過時欄位移開,或使用 searchFields 和 select 查詢參數來選擇要搜尋和回傳的欄位。 在物理上,欄位的定義和內容會保留在索引中,直到下一次重建時,當你套用省略該欄位的架構時。
更改欄位定義 欄位名稱、資料型態或特定 索引屬性 (可搜尋、可篩選、可排序、面表)的修訂需要全面重建。
將分析器指派到欄位 分析器 在索引中定義,指派到欄位,然後在索引過程中被調用,以告知標記的建立方式。 你可以隨時為索引新增分析器定義,但只能在欄位建立時指定分析器。 這對 分析器 和 indexAnalyzer 的特性都適用。 searchAnalyzer 屬性是例外(你可以將此屬性指派到現有欄位)。
更新或刪除索引中的分析器定義 除非重建整個索引,否則你無法刪除或更改索引中現有的分析器設定(分析器、標記器、標記過濾器或字元過濾器)。
在建議器中新增欄位 如果欄位已經存在,且你想把它加入 Suggesters 結構中,請重建索引。
升級你的服務或等級 如果你需要更多容量,可以看看是否能 升級服務 或 轉換到較高的收費方案。 如果沒有,你必須建立新服務並從頭重建索引。 為了幫助自動化這個流程,你可以使用一個程式碼範例,將索引備份到一系列 JSON 檔案中。 接著你可以在指定的搜尋服務中重新建立索引。

操作順序為:

  1. 先取得索引定義 ,以備未來參考或作為新版本的基礎。

  2. 考慮使用備份與還原方案來保存索引內容的副本。 解法分布在C#以及Python。 我們推薦 Python 版本,因為它比較最新。

    如果你的搜尋服務有容量,建立和測試新索引時,保留現有的索引。

  3. 取消現有的指數。 針對該索引的查詢會立即被捨棄。 請記住,刪除索引是不可逆的,會破壞欄位集合及其他結構的實體儲存空間。

  4. 發布修訂後的索引,請求內容包含變更或修改的欄位定義與配置。

  5. 將來自外部來源的文件載入索引。 文件會依據新架構的欄位定義與配置進行索引。

當你建立索引時,會為索引結構中的每個欄位分配實體儲存空間,每個可搜尋欄位建立反向索引,向量欄位則建立向量索引。 無法搜尋的欄位可用於篩選或表達式,但不會有反轉索引,也無法全文或模糊搜尋。 在索引重建中,這些反轉索引和向量索引會被刪除,並根據你提供的索引架構重新建立。

為了減少對應用程式程式碼的干擾,可以考慮 建立索引別名。 應用程式程式碼會參考別名,但你可以更新別名指向的索引名稱。

新增索引描述

索引有一個 description 屬性,當系統需要存取多個索引並根據描述做出決策時,你可以指定並使用它。 考慮一個模型情境協定(MCP)伺服器,必須在執行時選擇正確的索引。 決定可基於描述,而非僅僅依索引名稱。

索引描述是結構更新,你可以新增它而不用重建整個索引。

  • 字串長度最多為 4,000 字元。
  • 內容必須是人類可讀的,且必須以 Unicode 格式呈現。 你的使用情境應該決定要用哪種語言。

你可以透過 Azure 入口網站、最新穩定的 REST API 或提供此功能的 Azure SDK 套件,新增索引描述。

Azure 入口網站支援最新的預覽 API。

  1. 在Azure 入口網站中,進入您的搜尋服務。

  2. 在 搜尋管理>的索引中,選擇一個索引。

  3. 選擇編輯 JSON。

  4. 插入 "description",接著是描述。 數值必須少於 4,000 個字元,且必須以 Unicode 格式進行。

    Azure入口網站中索引的 JSON 定義截圖。

  5. 存下索引。

平衡工作負載

索引不會在背景執行,但搜尋服務會根據索引工作與持續查詢做平衡。 在索引過程中,你可以在Azure入口網站監控查詢請求,確保查詢能及時完成。

若編寫工作負載帶來不可接受的查詢延遲,請進行 效能分析 並檢視這些 效能提示 以尋找可能的緩解措施。

請留意最新消息

你可以在第一個文件載入後立即開始查詢索引。 如果你知道文件的 ID,Lookup Document REST API 會 回傳該特定文件。 如果要做更廣泛的測試,建議等索引完全載入後,再用查詢來驗證你預期看到的上下文。

你可以使用 搜尋檔案總管 或 REST 用戶端 來檢查內容是否更新。

如果你新增或重新命名欄位,請使用 Select 回傳該欄位:

"search": "*",
"select": "document-id, my-new-field, some-old-field",
"count": true

Azure 入口網站提供索引大小與向量索引大小。 在索引更新後,你可以查看這些數值,但請記得服務在處理變更時會有短暫的延遲,並要考慮到入口網站的刷新率,這可能會需要幾分鐘的時間。

重新索引故障排除

下表列出更新或重建索引時常見的問題及其解決方法。

問題 成因 解決方法
207 的回應結果參差不齊 有些文件成功了,有些則失敗了。 檢查回應中每個文件的 statusCode。 如果是 503,請節流要求並重試。
409 版本衝突 同時更新同一份文件。 將更新序列化到同一份文件,或是實作指數式回撤的重試。
429 太多請求 儲存配額超過或同時處理的請求過多。 刪除文件以騰出空間,或升級服務等級以增加容量。
503 號線無法提供服務 重載服役。 請等待並以指數退避方式重試。 考慮減少批次數量。
刪除後文件數量未變 刪除是非同步的。 等背景程序完成物理刪除,等待2到3分鐘。
新欄位回傳空值(null) 將欄位添加到資料結構中,但文件未重新索引。 執行索引器或推送更新文件來填入新欄位。
結構變更被拒絕 嘗試不相容的變更(重命名、型別變更)。 刪除並重建索引。 使用索引別名來減少停機時間。

參見