为 Azure Cosmos DB for NoSQL 中的数据编制索引,以便在 Azure AI 搜索中查询
本文将介绍如何配置索引器,该索引器从 Azure Cosmos DB for NoSQL 导入内容,并使内容在 Azure AI 搜索中可供搜索。
本文是对创建索引器的补充,其中包含特定于 Cosmos DB 的信息。 它使用 REST API 演示所有索引器通用的三部分工作流:创建数据源、创建索引、创建索引器。 提交“创建索引器”请求时,将提取数据。
由于术语可能会造成混淆,特此提示,Azure Cosmos DB 索引编制和 Azure AI 搜索索引编制属于不同的操作。 在 Azure AI 搜索中编制索引可在搜索服务中创建并加载搜索索引。
先决条件
一个 Azure Cosmos DB 帐户、数据库、容器和项。 对 Azure AI 搜索和 Azure Cosmos DB 使用同一个区域,以降低延迟并避免带宽费用。
针对 Azure Cosmos DB 集合的自动索引策略,设置为“一致”。 这是默认配置。 不建议使用延迟索引,可能会导致数据缺失。
读取权限。 “完全访问权限”连接字符串包含一个授予对内容的访问权限的密钥,但如果你使用的是标识 (Microsoft Entra ID),请确保为搜索服务托管标识分配了 Cosmos DB 帐户读取者角色和 Cosmos DB 内置数据读取者角色。
若要完成本文中的示例,你需要 Azure 门户或一个 REST 客户端。 如果使用 Azure 门户,请确保启用对所有公用网络的访问权限。 创建 Cosmos DB 索引器的其他方法包括 Azure SDK。
使用示例数据进行尝试
请按照以下说明在 Cosmos DB 中创建用于测试目的的容器和数据库。
从 GitHub 下载 HotelsData_toCosmosDB.JSON,以在 Cosmos DB 中创建一个包含示例 hotels 数据集子集的容器。
登录 Azure 门户并在 Cosmos DB 上创建帐户、数据库和容器。
在 Cosmos DB 中为新容器选择“数据资源管理器”,并提供以下值。
属性 值 数据库 新建 数据库 ID hotelsdb 在容器之间共享吞吐量 不要选中 容器 ID 酒店 分区键 /HotelId 容器吞吐量(自动缩放) 自动缩放 容器最大 RU/s 1000 在“数据资源管理器”中展开“hotelsdb”和“hotels”,然后选择“项”。
选择“上传项”,然后选择已从 GitHub 下载的 HotelsData_toCosmosDB.JSON 文件。
右键单击“项”并选择“新建 SQL 查询”。 默认查询为
SELECT * FROM c
。选择“执行查询”以运行该查询并查看结果。 你应该有 50 个 hotel 文档。
有了容器后,就可以使用 Azure 门户、REST 客户端或 Azure SDK 为数据编制索引了。
“说明”字段提供了最详细的内容。 你应该针对该字段进行全文搜索和可选矢量查询。
使用 Azure 门户
可以使用“导入数据”向导或“导入和矢量化数据”向导从 SQL 数据库表或视图自动编制索引。 这两个向导的数据源配置类似。
在“连接到数据”上,选择或验证数据源类型(即数据源类型是“Azure Cosmos DB”还是“NoSQL 帐户”)。
数据源名称是指 Azure AI 搜索中的数据源连接对象。 如果你使用矢量向导,则系统会使用向导工作流结束时指定的自定义前缀自动生成数据源名称。
指定数据库名称和集合。 查询为可选。 如果你有分层数据,想要导入特定切片,则可使用它。
指定身份验证方法,该方法可以是托管标识,也可以是内置 API 密钥。 如果未指定托管标识连接,Azure 门户会使用该密钥。
如果将 Azure AI 搜索配置为使用托管标识,并在 Cosmos DB 上创建角色分配,以向标识授予 Cosmos DB 帐户读取者和 Cosmos DB 内置数据读取者权限,则索引器可以使用 Microsoft Entra ID 和角色连接到 Cosmos DB。
对于导入和矢量化数据向导,可以指定进行更改和删除跟踪的选项。
默认情况下,支持通过
_ts
字段(时间戳)进行更改检测。 如果使用使用示例数据进行尝试中描述的方法上传内容,则会使用_ts
字段创建集合。删除检测要求集合中有一个预先存在的可用作软删除标志的顶级字段。 它应该是一个布尔字段(可以将其命名为 IsDeleted)。 将
true
指定为软删除值。 在搜索索引中,添加一个名为“IsDeleted”且已设置为可检索和可筛选的相应搜索字段。继续执行剩余步骤以完成该向导:
使用 REST API
本部分演示可创建数据源、索引和索引器的 REST API 调用。
定义数据源
数据源定义指定要编制索引的数据、凭据和用于标识数据更改的策略。 数据源是一个独立的资源,可由多个索引器使用。
创建或更新数据源以设置其定义:
POST https://[service name].search.azure.cn/datasources?api-version=2024-07-01 Content-Type: application/json api-key: [Search service admin key] { "name": "[my-cosmosdb-ds]", "type": "cosmosdb", "credentials": { "connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.cn;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]" }, "container": { "name": "[my-cosmos-db-collection]", "query": null }, "dataChangeDetectionPolicy": { "@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy", " highWaterMarkColumnName": "_ts" }, "dataDeletionDetectionPolicy": null, "encryptionKey": null, "identity": null }
将 "type" 设置为
"cosmosdb"
(必需)。 如果使用的是较旧的搜索 API 版本2017-11-11,则“type”的语法为"documentdb"
。 而对于 2019-05-06 及更高版本,请使用"cosmosdb"
。将“凭据”设置为连接字符串。 下一部分介绍受支持的格式。
将“容器”设置为集合。 “名称”属性是必填的,它指定要编制索引的数据库集合的 ID。 “查询”属性是可选的。 使用它将一个任意 JSON 文档平展成 Azure AI 搜索可索引的平面架构。
如果数据经常变动,且你希望索引器在后续运行时只获取新项和更新的项,则设置“dataChangeDetectionPolicy”。
如果要在删除源项时从搜索索引中删除搜索文档,则设置“dataDeletionDetectionPolicy”。
受支持的凭据和连接字符串
索引器可以使用以下连接连接到集合。
避免在终结点 URL 中包含端口号。 如果包含端口号,连接会失败。
完全访问权限连接字符串 |
---|
{ "connectionString" : "AccountEndpoint=https://<Cosmos DB account name>.documents.azure.cn;AccountKey=<Cosmos DB auth key>;Database=<Cosmos DB database id> " }` |
可以通过在左侧导航窗格中选择“密钥”,从 Azure 门户的 Azure Cosmos DB 帐户页中获取连接字符串。 请确保选择完整的连接字符串,而不只是一个密钥。 |
托管标识连接字符串 |
---|
{ "connectionString" : "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.DocumentDB/databaseAccounts/<your cosmos db account name>/;(ApiKind=[api-kind];)/(IdentityAuthType=[identity-auth-type])" } |
此连接字符串不需要帐户密钥,但必须拥有可使用托管标识进行连接的搜索服务。 对于面向 SQL API 的连接,可以从连接字符串中省略 ApiKind 。 有关 ApiKind 的详细信息,IdentityAuthType 请参阅使用托管标识设置与 Azure Cosmos DB 数据库的索引器连接。 |
使用查询形成索引数据
在“容器”下的“查询”属性中,可以指定一个 SQL 查询来平展嵌套的属性或数组、投影 JSON 属性并筛选要编制索引的数据。
示例文档:
{
"userId": 10001,
"contact": {
"firstName": "andy",
"lastName": "hoh"
},
"company": "microsoft",
"tags": ["azure", "cosmosdb", "search"]
}
筛选查询:
SELECT * FROM c WHERE c.company = "microsoft" and c._ts >= @HighWaterMark ORDER BY c._ts
平展查询:
SELECT c.id, c.userId, c.contact.firstName, c.contact.lastName, c.company, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts
投影查询:
SELECT VALUE { "id":c.id, "Name":c.contact.firstName, "Company":c.company, "_ts":c._ts } FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts
数组平展查询:
SELECT c.id, c.userId, tag, c._ts FROM c JOIN tag IN c.tags WHERE c._ts >= @HighWaterMark ORDER BY c._ts
不支持的查询(DISTINCT 和 GROUP BY)
不支持使用 DISTINCT 关键字和 GROUP BY 子句进行查询。 Azure AI 搜索依赖 SQL 查询分页来完全枚举查询的结果。 DISTINCT 关键字或 GROUP BY 子句与用于对结果进行分页的延续令牌均不兼容。
不受支持的查询示例:
SELECT DISTINCT c.id, c.userId, c._ts FROM c WHERE c._ts >= @HighWaterMark ORDER BY c._ts
SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name
SELECT TOP 4 COUNT(1) AS foodGroupCount, f.foodGroup FROM Food f GROUP BY f.foodGroup
尽管 Azure Cosmos DB 有一种解决方法来使用 ORDER BY 子句支持包含 DISTINCT 关键字的 SQL 查询分页,但它与 Azure AI 搜索不兼容。 查询将返回一个 JSON 值,而 Azure AI 搜索需要一个 JSON 对象。
-- The following query returns a single JSON value and isn't supported by Azure AI Search
SELECT DISTINCT VALUE c.name FROM c ORDER BY c.name
将搜索字段添加到索引
在搜索索引中,添加字段以接受源 JSON 文档或自定义查询投影的输出。 确保搜索索引架构与源数据兼容。 对于 Azure Cosmos DB 中的内容,搜索索引架构应对应于数据源中的 Azure Cosmos DB 项。
创建或更新索引以定义存储数据的搜索字段:
POST https://[service name].search.azure.cn/indexes?api-version=2024-07-01 Content-Type: application/json api-key: [Search service admin key] { "name": "mysearchindex", "fields": [{ "name": "rid", "type": "Edm.String", "key": true, "searchable": false }, { "name": "description", "type": "Edm.String", "filterable": false, "searchable": true, "sortable": false, "facetable": false, "suggestions": true } ] }
创建文档键字段 ("key": true)。 对于已分区集合,默认文档键是 Azure Cosmos DB
_rid
属性,Azure AI 搜索会自动将其重命名为rid
,因为字段名称不能以下划线字符开头。 此外,Azure Cosmos DB 的_rid
值包含了在 Azure AI 搜索键中无效的字符。 因此,_rid
值采用 Base64 编码。创建更多字段以添加更多可搜索的内容。 有关详细信息,请参阅创建索引。
映射数据类型
JSON 数据类型 | Azure AI 搜索字段类型 |
---|---|
Bool | Edm.Boolean、Edm.String |
类似于整数的数字 | Edm.Int32、Edm.Int64、Edm.String |
类似于浮点的数字 | Edm.Double、Edm.String |
String | Edm.String |
基元类型的数组,如 ["a", "b", "c"] | 集合 (Edm.String) |
类似于日期的字符串 | Edm.DateTimeOffset、Edm.String |
GeoJSON 对象,如 { "type": "Point", "coordinates": [long, lat] } | Edm.GeographyPoint |
其他 JSON 对象 | 空值 |
配置并运行 Azure Cosmos DB for NoSQL 索引器
创建索引和数据源后,便可以准备创建索引器。 索引器配置指定控制运行时行为的输入、参数和属性。
通过为索引器命名并引用数据源和目标索引来创建或更新索引器:
POST https://[service name].search.azure.cn/indexers?api-version=2024-07-01 Content-Type: application/json api-key: [search service admin key] { "name" : "[my-cosmosdb-indexer]", "dataSourceName" : "[my-cosmosdb-ds]", "targetIndexName" : "[my-search-index]", "disabled": null, "schedule": null, "parameters": { "batchSize": null, "maxFailedItems": 0, "maxFailedItemsPerBatch": 0, "base64EncodeKeys": false, "configuration": {} }, "fieldMappings": [], "encryptionKey": null }
如果字段名称或类型存在差异,或者需要在搜索索引中使用多个版本的源字段,请指定字段映射。
有关其他属性的详细信息,请参阅创建索引器。
创建索引器后,它会自动运行。 可以将“已禁用”设置为 true 以防止这种情况。 若要控制索引器执行,请按需运行索引器或按计划运行索引器。
检查索引器状态
若要监视索引器状态和执行历史记录,请在 Azure 门户中检查索引器执行历史记录,或发送“获取索引器状态”REST API 请求
执行历史记录包含最多 50 个最近完成的执行,它们按时间倒序排列,这样最新的执行最先显示。
为新文档和已更改的文档编制索引
索引器完全填充搜索索引后,建议运行后续的索引器,以便仅对数据库中的新文档和已更改的文档进行增量索引编制。
若要启用增量索引编制,请在数据源定义中设置“dataChangeDetectionPolicy”属性。 此属性告知索引器对数据使用哪种更改跟踪机制。
对于 Azure Cosmos DB 索引器,唯一支持的策略是使用 Azure Cosmos DB 提供的 _ts
(时间戳)属性的 HighWaterMarkChangeDetectionPolicy
。
以下示例演示具有更改检测策略的数据源定义:
"dataChangeDetectionPolicy": {
"@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
" highWaterMarkColumnName": "_ts"
},
注意
将 null
值分配给 Azure Cosmos DB 中的字段时,AI 搜索索引器无法区分 null
和缺少的字段值。 因此,如果索引中的字段为空,则它不会替换为 null
值,即使在数据库中专门进行了该修改。
增量索引和自定义查询
如果使用自定义查询来检索文档,请确保查询按 _ts
列对结果进行排序。 这会启用定期检查点,在出现故障时,Azure AI 搜索可以利用检查点提供增量操作。
在某些情况下,即使查询包含 ORDER BY [collection alias]._ts
子句,Azure AI 搜索也可能无法推断出查询是按照 _ts
进行排序的。 可以告知 Azure AI 搜索,结果是通过设置 assumeOrderByHighWaterMarkColumn
配置属性进行排序的。
要指定此提示,请按如下所示创建或更新索引器定义:
{
... other indexer definition properties
"parameters" : {
"configuration" : { "assumeOrderByHighWaterMarkColumn" : true } }
}
为已删除的文档编制索引
从集合中删除行时,通常还需要从搜索索引中删除这些行。 数据删除检测策略旨在有效识别已删除的数据项。 目前,唯一支持的策略是 Soft Delete
策略(删除标有某种类型的标志),它在数据源定义中指定如下:
"dataDeletionDetectionPolicy"": {
"@odata.type" : "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
"softDeleteColumnName" : "the property that specifies whether a document was deleted",
"softDeleteMarkerValue" : "the value that identifies a document as deleted"
}
如果使用自定义查询,请确保查询投影由 softDeleteColumnName
引用的属性。
softDeleteColumnName
必须是索引中的顶级字段。 不支持在复杂数据类型中使用嵌套字段作为 softDeleteColumnName
。
下面的示例创建具有软删除策略的数据源:
POST https://[service name].search.azure.cn/datasources?api-version=2024-07-01
Content-Type: application/json
api-key: [Search service admin key]
{
"name": "[my-cosmosdb-ds]",
"type": "cosmosdb",
"credentials": {
"connectionString": "AccountEndpoint=https://[cosmos-account-name].documents.azure.cn;AccountKey=[cosmos-account-key];Database=[cosmos-database-name]"
},
"container": { "name": "[my-cosmos-collection]" },
"dataChangeDetectionPolicy": {
"@odata.type": "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName": "_ts"
},
"dataDeletionDetectionPolicy": {
"@odata.type": "#Microsoft.Azure.Search.SoftDeleteColumnDeletionDetectionPolicy",
"softDeleteColumnName": "isDeleted",
"softDeleteMarkerValue": "true"
}
}
使用 .NET
对于通过 SQL API 协议访问的数据,可以使用 .NET SDK 通过索引器进行自动化。 我们建议查看前面的 REST API 部分,以了解相关概念、工作流和要求。 然后,可以参阅以下 .NET API 参考文档,在托管代码中实现 JSON 索引器:
- azure.search.documents.indexes.models.searchindexerdatasourceconnection
- azure.search.documents.indexes.models.searchindexerdatasourcetype
- azure.search.documents.indexes.models.searchindex
- azure.search.documents.indexes.models.searchindexer
后续步骤
现在可以控制如何运行索引器、监视状态或计划索引器执行。 以下文章适用于从 Azure Cosmos DB 拉取内容的索引器: