为 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 搜索中编制索引可在搜索服务中创建并加载搜索索引。

先决条件

定义数据源

数据源定义指定要编制索引的数据、凭据和用于标识数据更改的策略。 数据源是一个独立的资源,可由多个索引器使用。

  1. 创建或更新数据源以设置其定义:

    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
    }
    
  2. 将 "type" 设置为 "cosmosdb"(必需)。 如果使用的是较旧的搜索 API 版本2017-11-11,则“type”的语法为 "documentdb"。 而对于 2019-05-06 及更高版本,请使用 "cosmosdb"

  3. 将“凭据”设置为连接字符串。 下一部分介绍受支持的格式。

  4. 将“容器”设置为集合。 “名称”属性是必填的,它指定要编制索引的数据库集合的 ID。 “查询”属性是可选的。 使用它将一个任意 JSON 文档平展成 Azure AI 搜索可索引的平面架构。

  5. 如果数据经常变动,且你希望索引器在后续运行时只获取新项和更新的项,则设置“dataChangeDetectionPolicy”

  6. 如果要在删除源项时从搜索索引中删除搜索文档,则设置“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 项

  1. 创建或更新索引以定义存储数据的搜索字段:

    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
        }
      ]
    }
    
  2. 创建文档键字段 ("key": true)。 对于已分区集合,默认文档键是 Azure Cosmos DB _rid 属性,Azure AI 搜索会自动将其重命名为 rid,因为字段名称不能以下划线字符开头。 此外,Azure Cosmos DB 的 _rid 值包含了在 Azure AI 搜索键中无效的字符。 因此,_rid 值采用 Base64 编码。

  3. 创建更多字段以添加更多可搜索的内容。 有关详细信息,请参阅创建索引

映射数据类型

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 索引器

创建索引和数据源后,便可以准备创建索引器。 索引器配置指定控制运行时行为的输入、参数和属性。

  1. 通过为索引器命名并引用数据源和目标索引来创建或更新索引器

    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
    }
    
  2. 如果字段名称或类型存在差异,或者需要在搜索索引中使用多个版本的源字段,请指定字段映射

  3. 有关其他属性的详细信息,请参阅创建索引器

创建索引器后,它会自动运行。 可以将“已禁用”设置为 true 以防止这种情况。 若要控制索引器执行,请按需运行索引器按计划运行索引器

检查索引器状态

若要监视索引器状态和执行历史记录,请发送获取索引器状态请求:

GET https://myservice.search.azure.cn/indexers/myindexer/status?api-version=2024-07-01
  Content-Type: application/json  
  api-key: [admin key]

响应包括状态和已处理的项数。 它应如下例所示:

    {
        "status":"running",
        "lastResult": {
            "status":"success",
            "errorMessage":null,
            "startTime":"2022-02-21T00:23:24.957Z",
            "endTime":"2022-02-21T00:36:47.752Z",
            "errors":[],
            "itemsProcessed":1599501,
            "itemsFailed":0,
            "initialTrackingState":null,
            "finalTrackingState":null
        },
        "executionHistory":
        [
            {
                "status":"success",
                "errorMessage":null,
                "startTime":"2022-02-21T00:23:24.957Z",
                "endTime":"2022-02-21T00:36:47.752Z",
                "errors":[],
                "itemsProcessed":1599501,
                "itemsFailed":0,
                "initialTrackingState":null,
                "finalTrackingState":null
            },
            ... earlier history items
        ]
    }

执行历史记录包含最多 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 Cosmos DB 拉取内容的索引器: