註
Azure AI 搜尋服務 可透過 Azure 入口網站、REST API 及 Azure SDK 取得。 它同時也是 Foundry IQ 的基礎,這是一個管理式知識層,能將企業內容轉化為可重複使用、權限感知的知識庫,供 Microsoft Foundry 入口網站中的代理使用。
本文說明如何在 Azure AI 搜尋服務 中透過增量索引來更新現有索引,並進行結構變更或內容變更。
先決條件
更新或重建索引的權限:
- 基於金鑰的認證:用於搜尋服務的 管理員 API 金鑰 。
- 基於角色的認證:用於文件更新的 搜尋索引資料貢獻 者角色,或用於結構變更的 搜尋服務貢獻 者。
SDK 開發時,請安裝 Azure Search 用戶端函式庫:
- Python: azure-search-documents
- .NET:Azure.Search.Documents
- JavaScript: @azure/search-documents
- Java: azure-search-documents
提示
在開發過程中,當反覆調整索引設計時,常常會捨棄並重建索引。 使用少數具代表性的資料樣本,讓重新索引更快。 對於生產架構的變更,請建立並並排測試一個新的索引,然後使用 索引別名 交換索引,而不更改應用程式代碼。
更新內容
增量索引與索引與來源資料變化同步是大多數搜尋應用的基本功能。 本節說明透過 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)")
更新索引結構
索引結構定義了搜尋服務中建立的實體資料結構,因此你無法做太多結構變更,除非需要完全重建。
更新但無需重建
以下列表列舉可無縫導入現有索引的結構變更。 通常,該清單包含查詢執行時使用的新欄位與功能。
- 新增 索引描述
- 新增欄位
- 將屬性設定
retrievable在現有欄位上 - 更新已有
searchAnalyzer之欄位上的indexAnalyzer - 在索引中新增一個分析 器定義 (可套用到新欄位)
- 新增、更新或刪除 評分檔案
- 新增、更新或刪除 同義地圖
- 新增、更新或刪除 語意配置
- 新增、更新或刪除 CORS 設定
操作順序為:
當你更新索引結構以新增欄位時,索引中現有的文件會被賦予該欄位的空值。 在下一個索引工作中,外部來源資料的值會取代 Azure AI 搜尋服務 新增的空值。
更新期間不應有查詢中斷,但查詢結果會隨著更新生效而變化。
需要重建的更新
部分改裝需要刪除並重建現有索引,將現有索引換成新的。
| 行動 | 描述 |
|---|---|
| 刪除欄位 | 要實體移除欄位的所有痕跡,你必須重建索引。 當立即重建不切實際時,你可以修改應用程式程式碼,將存取權從過時欄位移開,或使用 searchFields 和 select 查詢參數來選擇要搜尋和回傳的欄位。 在物理上,欄位的定義和內容會保留在索引中,直到下一次重建時,當你套用省略該欄位的架構時。 |
| 更改欄位定義 | 欄位名稱、資料型態或特定 索引屬性 (可搜尋、可篩選、可排序、面表)的修訂需要全面重建。 |
| 將分析器指派到欄位 | 分析器 在索引中定義,指派到欄位,然後在索引過程中被調用,以告知標記的建立方式。 你可以隨時為索引新增分析器定義,但只能在欄位建立時指定分析器。 這對 分析器 和 indexAnalyzer 的特性都適用。 searchAnalyzer 屬性是例外(你可以將此屬性指派到現有欄位)。 |
| 更新或刪除索引中的分析器定義 | 除非重建整個索引,否則你無法刪除或更改索引中現有的分析器設定(分析器、標記器、標記過濾器或字元過濾器)。 |
| 在建議器中新增欄位 | 如果欄位已經存在,且你想把它加入 Suggesters 結構中,請重建索引。 |
| 升級你的服務或等級 | 如果你需要更多容量,可以看看是否能 升級服務 或 轉換到較高的收費方案。 如果沒有,你必須建立新服務並從頭重建索引。 為了幫助自動化這個流程,你可以使用一個程式碼範例,將索引備份到一系列 JSON 檔案中。 接著你可以在指定的搜尋服務中重新建立索引。 |
操作順序為:
先取得索引定義 ,以備未來參考或作為新版本的基礎。
考慮使用備份與還原方案來保存索引內容的副本。 解法分布在C#以及Python。 我們推薦 Python 版本,因為它比較最新。
如果你的搜尋服務有容量,建立和測試新索引時,保留現有的索引。
取消現有的指數。 針對該索引的查詢會立即被捨棄。 請記住,刪除索引是不可逆的,會破壞欄位集合及其他結構的實體儲存空間。
發布修訂後的索引,請求內容包含變更或修改的欄位定義與配置。
將來自外部來源的文件載入索引。 文件會依據新架構的欄位定義與配置進行索引。
當你建立索引時,會為索引結構中的每個欄位分配實體儲存空間,每個可搜尋欄位建立反向索引,向量欄位則建立向量索引。 無法搜尋的欄位可用於篩選或表達式,但不會有反轉索引,也無法全文或模糊搜尋。 在索引重建中,這些反轉索引和向量索引會被刪除,並根據你提供的索引架構重新建立。
為了減少對應用程式程式碼的干擾,可以考慮 建立索引別名。 應用程式程式碼會參考別名,但你可以更新別名指向的索引名稱。
新增索引描述
索引有一個 description 屬性,當系統需要存取多個索引並根據描述做出決策時,你可以指定並使用它。 考慮一個模型情境協定(MCP)伺服器,必須在執行時選擇正確的索引。 決定可基於描述,而非僅僅依索引名稱。
索引描述是結構更新,你可以新增它而不用重建整個索引。
- 字串長度最多為 4,000 字元。
- 內容必須是人類可讀的,且必須以 Unicode 格式呈現。 你的使用情境應該決定要用哪種語言。
你可以透過 Azure 入口網站、最新穩定的 REST API 或提供此功能的 Azure SDK 套件,新增索引描述。
Azure 入口網站支援最新的預覽 API。
在Azure 入口網站中,進入您的搜尋服務。
在 搜尋管理>的索引中,選擇一個索引。
選擇編輯 JSON。
插入
"description",接著是描述。 數值必須少於 4,000 個字元,且必須以 Unicode 格式進行。
存下索引。
平衡工作負載
索引不會在背景執行,但搜尋服務會根據索引工作與持續查詢做平衡。 在索引過程中,你可以在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) | 將欄位添加到資料結構中,但文件未重新索引。 | 執行索引器或推送更新文件來填入新欄位。 |
| 結構變更被拒絕 | 嘗試不相容的變更(重命名、型別變更)。 | 刪除並重建索引。 使用索引別名來減少停機時間。 |