更新或重建 Azure AI 搜尋服務中的索引
本文說明如何透過累加式索引編製,使用結構描述變更或內容變更來更新 Azure AI 搜尋服務中的現有索引。 包含需要重建的情況,並提供可降低重建對進行中查詢要求影響的建議。
在活躍開發期間,當您在反覆設計索引時,通常會卸載並重建索引。 大部分的開發人員會使用其資料的小型代表性範例,以便加快重新編製索引的速度。
若要變更生產環境中既有應用程式的結構描述,建議您建立並測試會與現有索引並存執行的新索引。 使用索引別名來交換新的索引,以便避免變更應用程式程序代碼。
更新內容
對大多數搜尋應用程式來說,以累加方式對來源資料的變更進行索引編製和同步處理是很重要的操作。 本節說明透過 REST API 更新搜尋索引中欄位內容的工作流程,但 Azure SDK 提供對等的功能。
要求的本文包含一或多個要編製索引的檔。 檔會以唯一區分大小寫的索引鍵來識別。 每個檔都與動作相關聯:「upload」、“delete”、“merge”或 “mergeOrUpload”。 上傳要求必須包含文件數據做為一組索引鍵/值組。
{
"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 (key/value pairs matching index schema)
...
},
...
]
}
首先,使用 API 來載入檔,例如 檔 - 索引 (REST) 或 Azure SDK 中的對等 API。 如需索引編製技術的詳細資訊,請參閱載入文件。
針對大型更新、批處理(每個批次最多 1,000 份檔,或每個批次約 16 MB,建議先有限制),並大幅改善編製索引效能。
@search.action
在 API 上設定 參數,以判斷對現有文件的影響。動作 效果 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 }]
,則會議室欄位[{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]
的最終值為 。 它不會附加或合併新的和現有的值。mergeOrUpload 如果文件存在,行為會和合併一樣,如果是新文件,則會上傳。 這是累加式更新最常見的動作。 上傳 類似 "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 | 已成功修改或刪除檔。 | n/a | 刪除作業為等冪。 也就是說,即使索引中沒有檔索引鍵,嘗試使用該索引鍵的刪除作業會導致 200 狀態代碼。 |
201 | 已成功建立檔。 | n/a | |
400 | 文件中發生錯誤,導致無法編製索引。 | No | 回應中的錯誤訊息表示檔發生錯誤。 |
404 | 無法合併檔,因為指定的索引鍵不存在於索引中。 | No | 上傳時不會發生此錯誤,因為它們會建立新的檔,而且不會因為其等冪而發生刪除。 |
409 | 嘗試編製檔索引時,偵測到版本衝突。 | Yes | 當您嘗試並行對相同的文件編製索引時,也可能會發生此情況。 |
422 | 索引暫時無法使用,因為它已更新為 『allowIndexDowntime』 旗標設定為 『true』。 | Yes | |
503 | 您的搜尋服務暫時無法使用,可能是因為負載過重。 | Yes | 在此情況下,您的程式碼在重試之前應等待,否則可能會導致服務長時間無法使用。 |
如果您的用戶端程式代碼經常遇到 207 回應,其中一個可能的原因是系統負載不足。 您可以檢查 503 的 statusCode 屬性來確認這一點。 如果 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=2024-07-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=2024-07-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=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
更新索引架構
索引結構描述會定義在搜尋服務上建立的實體資料結構,因此,不進行完整重建就很難進行許多結構描述變更。
沒有重建的更新
下列清單會列舉可順暢地引入到現有索引的結構描述變更。 一般而言,清單中會包含查詢執行期間所使用的新欄位和新功能。
- 新增欄位
- 對現有欄位設定
retrievable
屬性 - 對具有現有
indexAnalyzer
的欄位更新searchAnalyzer
- 在索引中新增分析器定義(可套用至新欄位)
- 新增、更新或刪除 評分配置檔
- 新增、更新或刪除 synonymMaps
- 新增、更新或刪除 語意設定
- 新增、更新或刪除 CORS 設定
作業順序為:
當您更新索引結構描述以包含新欄位時,索引中的現有文件會針對欄位獲得 null 值。 在執行下一個編制作業時,來自外部來源資料的值便會取代 Azure AI 搜尋服務所新增的 null。
更新期間應該不會有查詢中斷的情況,但查詢結果會隨著更新的生效而不同。
需要重建的更新
某些修改需要索引卸除和重建,以新的索引取代目前的索引。
動作 | 描述 |
---|---|
刪除欄位 | 若要實體上移除欄位的所有追蹤,您必須重建索引。 若無法立即重建,您可以修改應用程式的程式碼以重新導向對於已淘汰欄位的存取,或使用 searchFields 並選取查詢參數來選擇要搜尋和傳回的欄位。 實體上,在您下次套用省略問題欄位的結構描述重建之前,欄位定義和內容都會保留在索引中。 |
變更欄位定義 | 修改欄位名稱、資料類型或特定索引屬性 (可搜尋、可篩選、可排序、可面向化) 需要完整重建。 |
將分析器指派給欄位 | 分析器會在索引中定義、指派給欄位,然後在編製索引期間叫用以指示令牌的建立方式。 您可以隨時將新分析器定義新增至索引,但當欄位建立後,您只能指派分析器。 這適用於 analyzer 和 indexAnalyzer 屬性。 searchAnalyzer 屬性是例外狀況 (您可以將此屬性指派給現有欄位)。 |
更新或刪除索引中的分析器定義 | 您無法刪除或變更索引中的現有分析器組態 (分析器、權杖化工具、權杖篩選器或 char 篩選器),除非您重建整個索引。 |
將欄位新增至建議工具 | 如果已有欄位存在,且您想要將它新增至建議工具建構中,請重建索引。 |
切換階層 | 不支援就地升級。 如果您需要更多容量,請建立新的服務,並徹底重建您的索引。 為了協助將此程序自動化,您可以使用這個 Azure AI 搜尋服務 .NET 範例存放庫中的 index-backup-restore 範例程式碼。 此應用程式會將您的索引備份到一系列 JSON 檔案,然後在您指定的搜尋服務中重新建立索引。 |
作業順序為:
如果您需要索引定義以供日後參考,或作為新版本基礎使用,請取得索引定義。
考慮使用備份與還原解決方案來保留索引內容的複本。 有 C# 和 Python 版本的解決方案。 建議使用 Python 版本,因為這個版本比較新。
如果您有搜尋服務的容量,請在建立和測試新索引時保留現有的索引。
卸除現有索引。 目標是該索引的查詢會立即卸除。 請記住,刪除索引是無法復原的動作,這樣會終結欄位集合和其他建構的實體儲存體。
發佈經過修訂的索引,讓要求的本文包含經過變更或修改的欄位定義和設定。
使用來自外部來源的文件載入索引 \(英文\)。 系統便會使用新結構描述的欄位定義和設定為文件編製索引。
當您建立索引時,系統會針對索引結構描述中的每個欄位配置實體儲存體,並為每個可搜尋欄位建立反向索引,以及為每個向量欄位建立向量索引。 不可搜尋的欄位可用於篩選條件或運算式中,但不會有反向索引且不是可全文或模糊搜尋。 在重建索引時,這些反向索引和向量索引會被刪除並根據您提供的索引結構描述來重新建立。
若要將應用程式程式代碼中斷降至最低,請考慮 建立索引別名。 應用程式程式代碼會參考別名,但您可以更新別名所指向的索引名稱。
平衡工作負載
索引不會在背景中執行,但搜尋服務會針對進行中的查詢平衡任何索引編製作業。 在編制索引期間,您可以監視 Azure 入口網站 中的查詢要求,以確保查詢會及時完成。
如果為工作負載編製索引會產生令人無法接受的查詢延遲程度,請進行效能分析,並檢閱這些效能秘訣以便能降低風險。
檢查更新
第一個文件載入之後,您就可以開始查詢索引。 如果您知道文件的別碼,查閱文件 REST API \(英文\) 可傳回特定文件。 若要進行更廣泛的測試,您應該等到索引完全載入,然後使用查詢來確認您預期會看到的內容。
如果您新增或重新命名字段,請使用 select 傳回該欄位:
"search": "*",
"select": "document-id, my-new-field, some-old-field",
"count": true
Azure 入口網站會提供索引大小和向量索引大小。 您可以在更新索引之後檢查這些值,但請記住,服務在處理變更時應該會有稍微延遲的情形,也請記得考慮入口網站的重新整理速率,時間可能是幾分鐘。
刪除孤立文件
Azure AI 搜尋服務支援文件層級的作業,以便您可以單獨查閱、更新和刪除特定文件。 下列範例說明如何刪除文件。
刪除文件並不會立即釋放索引中的空間。 每隔幾分鐘,背景程序就會執行實體刪除。 無論您使用 Azure 入口網站 或 API 傳回索引統計數據,您都可以預期在 Azure 入口網站 和 API 計量中反映刪除之前會有一點延遲。
識別哪一個欄位是文件索引鍵。 在 Azure 入口網站 中,您可以檢視每個索引的欄位。 文件索引鍵是字串欄位,會以鑰匙圖示表示,使其更容易找到。
檢查文件索引鍵欄位的值:
search=*&$select=HotelId
。 簡單的字串是直接易懂的,但如果索引使用 base-64 編碼欄位,或是從parsingMode
設定中產生搜尋文件,則您可能會使用您不熟悉的值。查閱文件以確認文件 ID 的值,並在刪除之前檢閱其內容。 在要求中指定索引鍵或文件 ID。 下列範例說明旅館範例索引的一個簡單字串,以及 cog-search-demo 索引之metadata_storage_path 索引鍵的 base-64 編碼字串。
GET https://[service name].search.windows.net/indexes/hotel-sample-index/docs/1111?api-version=2024-07-01
GET https://[service name].search.windows.net/indexes/cog-search-demo/docs/aHR0cHM6Ly9oZWlkaWJsb2JzdG9yYWdlMi5ibG9iLmNvcmUud2luZG93cy5uZXQvY29nLXNlYXJjaC1kZW1vL2d1dGhyaWUuanBn0?api-version=2024-07-01
使用 delete
@search.action
刪除文件,以將文件從搜尋索引中移除。POST https://[service name].search.windows.net/indexes/hotels-sample-index/docs/index?api-version=2024-07-01 Content-Type: application/json api-key: [admin key] { "value": [ { "@search.action": "delete", "id": "1111" } ] }