你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
注意
Azure AI 搜索可通过Azure门户、REST API 和Azure SDK获取。 它也是 Foundry IQ 的基础;Foundry IQ 是一个托管式知识层,可将企业内容转化为供 Microsoft Foundry 门户中的智能体使用的、可复用且具备权限感知能力的知识库。
本文介绍如何通过增量索引通过架构更改或内容更改更新Azure AI 搜索中的现有索引。
先决条件
更新或重新生成索引的权限:
- 基于密钥的身份验证:搜索服务的 管理员 API 密钥 。
- 基于角色的身份验证:用于文档更新的搜索索引数据贡献者角色,或用于架构更改的搜索服务贡献者角色。
对于 SDK 开发,请安装Azure搜索客户端库:
- 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 - Index (REST) 或Azure SDK中的等效 API。 有关索引技术的详细信息,请参阅 “加载文档”。
对于大型更新,建议进行批处理(每批最多 1,000 个文档,或每批约 16 MB,以先到者为准),这将显著提高索引性能。
设置
@search.actionAPI 上的参数以确定对现有文档的影响。 用于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 | 已成功修改或删除文档。 | n/a | 删除操作是幂等的。 也就是说,即使索引中不存在文档键,尝试使用该键执行删除操作会导致 200 状态代码。 |
| 201 | 已成功创建文档。 | n/a | |
| 400 | 文档中存在错误,导致无法被编入索引。 | 不 | 响应中的错误消息指示文档出错。 |
| 404 | 无法合并文档,因为索引中不存在给定键。 | 不 | upload 不会发生此错误,因为它们创建新文档,delete 也不会发生此错误,因为它们是幂等的。 |
| 409 | 尝试为文档编制索引时检测到版本冲突。 | 是的 | 尝试多次为同一文档编制索引时,可能会发生这种情况。 |
| 422 | 索引暂时不可用,因为在将“allowIndexDowntime”标志设置为“true”的情况下更新了它。 | 是的 | |
| 429 | 请求过多 | 是的 | 如果在编制索引期间收到此错误代码,则通常意味着存储不足。 接近 存储限制时,服务可以进入在删除某些文档之前无法添加或更新的状态。 有关详细信息,请参阅 “规划和管理容量 ”(如果需要更多存储空间)或通过删除文档释放空间。 |
| 503 | 搜索服务暂时不可用,可能是由于负载过大。 | 是的 | 在这种情况下,您的代码应在重试前等待,否则可能有延长服务不可用时间的风险。 |
如果客户端代码经常遇到 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搜索操作。有效负载必须包含要添加、更新或删除的每个文档的密钥或标识符。
如果索引包含矢量字段,并且将属性设置为
storedfalse,请确保在部分文档更新中提供矢量,即使该值保持不变。 设置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}}
Reference:Documents - Index、 Lookup Document
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)")
Reference:SearchClient,merge_or_upload_documents
更新索引架构
索引架构定义了在搜索服务上创建的物理数据结构,因此,要进行架构更改通常需要完全重建。
无需重建的更新
以下列表枚举了可无缝引入现有索引的架构更改。 通常,该列表包括查询执行期间使用的新字段和功能。
- 添加 索引说明
- 添加新字段
- 在
retrievable现有字段上设置属性 - 对具有现有
searchAnalyzer的字段更新indexAnalyzer - 在索引中添加新的 分析器定义 (可应用于新字段)
- 添加、更新或删除 计分配置文件
- 添加、更新或删除 同义词映射
- 添加、更新或删除 语义配置
- 添加、更新或删除 CORS 设置
操作顺序为:
更新索引架构以包含新字段时,将为索引中的现有文档提供该字段的 null 值。 在下一个索引作业中,外部源数据中的值将替换Azure AI 搜索添加的 null 值。
更新期间不应发生查询中断,但随着更新生效,查询结果将有所不同。
需要重建的更新
某些修改需要删除和重新生成索引,将当前索引替换为新的索引。
| 行动 | 描述 |
|---|---|
| 删除字段 | 若要以物理方式删除字段的所有跟踪,必须重新生成索引。 在立即重新生成不可行时,可修改应用程序代码以重定向访问,使其远离过时的字段,或者使用 searchFields 和 select 查询参数来选择要搜索和返回的字段。 从物理上看,字段定义和内容会一直保留在索引中,直到下次重建时,你应用省略此字段的架构。 |
| 更改字段定义 | 对字段名称、数据类型或特定的索引属性(可搜索、可筛选、可排序、可查找)的修改需要完全重新生成。 |
| 将分析器分配到字段 | 分析器 在索引中定义,分配给字段,然后在编制索引期间调用,以告知令牌的创建方式。 可以随时向索引添加新的分析器定义,但只能在创建字段时 分配 分析器。 这适用于 分析器和indexAnalyzer 属性。 searchAnalyzer 属性是一个例外(可以将此属性分配给现有字段)。 |
| 更新或删除索引中的分析器定义 | 除非重新生成整个索引,否则不能删除或更改索引中的现有分析器配置(分析器、tokenizer、令牌筛选器或字符筛选器)。 |
| 向建议器添加字段 | 如果字段已存在,并且想要将其添加到 建议器 构造,请重新生成索引。 |
| 升级服务或档次 | 如果需要更多容量,请检查是否可以 升级服务 或 切换到更高的定价层。 否则,必须创建新服务并从头开始重新生成索引。 为了帮助自动执行此过程,可以使用将索引备份到一系列 JSON 文件的代码示例。 然后,可以在指定的搜索服务中重新创建索引。 |
操作顺序为:
如果需要索引定义以供将来参考,或用作新版本的基础,请获取索引定义。
请考虑使用备份和还原解决方案来保留索引内容的副本。 C# 和 Python 中有解决方案。 建议使用Python版本,因为它更最新。
如果搜索服务具有容量,请在创建和测试新索引时保留现有索引。
删除现有索引。 将立即删除以索引为目标的查询。 请记住,删除索引是不可逆转的,销毁字段集合和其他构造的物理存储。
发布修订后的索引,其中请求正文包括已更改或修改的字段定义和配置。
通过外部源使用文件加载索引。 文档使用新架构的字段定义和配置编制索引。
创建索引时,将为索引架构中的每个字段分配物理存储,为每个可搜索字段创建倒排索引,并为每个向量字段创建矢量索引。 不可搜索的字段可用于筛选器或表达式,但不包含倒排索引,并且不能全文搜索或模糊搜索。 在索引重新生成时,会根据提供的索引架构删除和重新创建这些倒排索引和向量索引。
若要最大程度地减少应用程序代码中断,请考虑 创建索引别名。 应用程序代码引用别名,但你可以更新别名指向的索引的名称。
添加索引说明
索引具有一个 description 属性,可以在系统必须访问多个索引并根据说明做出决策时指定和使用该属性。 请考虑模型上下文协议 (MCP) 服务器,该服务器必须在运行时选取正确的索引。 决策可以基于说明而不是仅基于索引名称。
索引说明是架构更新,无需重新生成整个索引即可添加它。
- 字符串长度最大为 4,000 个字符。
- 在 Unicode 中,内容必须是人可读的。 用例应确定要使用的语言。
可以通过Azure门户、最新的稳定 REST API 或提供该功能的Azure SDK包添加索引说明。
Azure门户支持最新的预览 API。
在 Azure 门户 中转到你的搜索服务。
在 “搜索管理>索引”下,选择一个索引。
选择 “编辑 JSON”。
插入
"description",然后是说明。 该值必须小于 4,000 个字符,并且必须位于 Unicode 中。
保存索引。
均衡工作负荷
索引不会在后台运行,但搜索服务会将任何索引作业与正在进行的查询平衡。 在编制索引期间,可以在Azure门户中监视查询请求,以确保查询及时完成。
如果索引工作负荷引入不可接受的查询延迟级别,请执行 性能分析 并查看这些 性能提示 ,了解潜在的缓解措施。
检查更新
加载第一个文档后,即可开始查询索引。 如果知道文档的 ID, 查找文档 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 分钟,让后台进程完成物理删除。 |
| 新字段返回空值 | 字段已添加到架构,但未重新索引文档。 | 运行索引器或推送更新的文档以填充新字段。 |
| 架构更改被拒绝 | 尝试的不兼容更改(重命名,类型更改)。 | 删除并重新生成索引。 使用索引别名将停机时间降到最低。 |