Azure AI 搜索中的索引投影

重要

根据补充使用条款,索引投影以公共预览版的形式提供。 可以通过 2023-10-01-Preview REST API、Azure 门户以及在更新后可以包括此功能的 beta 版本客户端库来获取此投影。

索引投影是技能组定义的一个组件,用于定义辅助索引的形状。支持一对多索引模式,其中,来自扩充管道的内容可以针对多个索引。

索引投影采用由扩充管道生成的 AI 扩充的内容,并在搜索服务上的辅助索引中对其编制索引(与索引器默认针对的索引不同)。 使用索引投影,还可以在编制索引之前重塑数据,以一种独特的方式,使你能够将扩充项的数组分成目标索引中的多个搜索文档,又称为“一对多”编制索引。 “一对多”索引对于数据分块场景非常有用,其中你可能希望有一个用于未分块内容的主索引,和一个用于已分块内容的辅助索引。

如果你过去使用过认知技能,就已经知道技能组创建扩充内容。 技能组通过一系列调用原子转换的扩充(例如识别实体或翻译文本)来移动文档。 默认情况下,在技能组中处理的一个文档会映射到搜索索引中的单个文档。 这意味着,如果对输入文本执行分块,然后在每个区块上执行扩充,则通过 outputFieldMappings 映射时索引中的结果是生成的扩充的数组。 借助索引投影,可以定义一个上下文,将扩充数据的每个区块映射到其自己的搜索文档。 这样,你就可以将文档的扩充数据的一对多映射应用于搜索索引。

索引投影定义

索引投影是在技能组定义中定义的,主要定义为选择器数组,其中每个选择器对应于搜索服务上的一个不同的目标索引。 每个选择器需要以下参数作为其定义的一部分:

  • targetIndexName:在其中对索引投影数据编制索引的搜索服务上的索引的名称。
  • parentKeyFieldName:包含父文档的键值的目标索引中的字段的名称。
  • sourceContext:定义将数据映射到各个搜索文档的粒度的扩充注释。 有关详细信息,请参阅技能上下文和输入注释语言
  • mappings:扩充数据到搜索索引中的字段的映射数组。 每个映射都包含:
    • name:应在其中对数据编制索引的搜索索引中的字段的名称。
    • source:应从中拉取数据的扩充注释路径。

每个 mapping 还可以递归方式使用可选的 sourceContextinputs 字段定义数据,类似于知识存储整形程序技能。 使用这些参数,可以调整要在搜索索引的类型 Edm.ComplexType 的字段中编制索引的数据。

targetIndexName 参数中定义的索引具有以下要求:

  • 在创建包含索引投影定义的技能组之前必须已在搜索服务上创建。
  • 必须包含具有 parentKeyFieldName 参数中定义的名称的字段。 此字段必须是 Edm.String 类型的,不能是键字段,并且必须将“可筛选”设置为 true。
  • 键字段必须将“可搜索”设置为 true,且使用 keyword 分析器定义。
  • 必须为 mappings 中定义的每个 name 定义字段,其中所有字段都不能是键字段。

下面是索引投影定义的示例有效负载,你可以使用它将拆分技能的各个页面输出投影为搜索索引中其自己的文档。

"indexProjections": {
    "selectors": [
        {
            "targetIndexName": "myTargetIndex",
            "parentKeyFieldName": "ParentKey",
            "sourceContext": "/document/pages/*",
            "mappings": [
                {
                    "name": "chunk",
                    "source": "/document/pages/*"
                }
            ]
        }
    ]
}

处理父文档

由于索引投影可有效地为通过技能组运行的每个“父”文档生成“子”文档,因此还可以选择以下选项来处理“父”文档的索引。

  • 若要将父文档和子文档置于不同的索引中,只需确保索引器定义的 targetIndexName 与索引投影选择器中定义的 targetIndexName 不同。

  • 若要在同一索引中对父文档和子文档编制索引,需要确保目标索引的架构同时适用于索引器定义中定义的 fieldMappingsoutputFieldMappings,以及索引投影选择器中定义的 mappings。 然后,只需为索引器定义和索引投影选择器提供相同的 targetIndexName

  • 若要忽略父文档并仅对子文档编制索引,仍然需要在索引器定义中提供 targetIndexName(只需提供与为索引投影选择器提供的相同名称)。 然后定义 selectors 定义旁边的单独的 parameters 对象,并将 projectionMode 键设置为 skipIndexingParentDocuments,如下所示:

    "indexProjections": {
        "selectors": [
            ...
        ],
        "parameters": {
            "projectionMode": "skipIndexingParentDocuments"
        }
    }
    

REST API 版本 2023-10-01-Preview 可用于通过添加技能组来创建索引投影。

内容生命周期

如果索引器数据源支持更改跟踪和删除检测,索引过程可以同步主索引和辅助索引以选取这些更改。

每次运行索引器和技能组时,如果技能组或基础源数据已更改,索引投影就会更新。 索引器选取的任何更改都将通过扩充过程传播到索引中的投影,从而确保投影数据是原始数据源中内容的当前表示形式。

注意

虽然可以使用索引推送 API 手动编辑已投影文档中的数据,但如果源数据中的文档已更新,则任何编辑都会在下一次管道调用时被覆盖。

投影的键值

每个索引投影文档都包含索引器生成的唯一标识键,以确保唯一性,让更改和删除跟踪可以正常运行。 该键包含以下各段:

  • 用于保证唯一性的随机哈希。 如果在索引器运行之间更新父文档,则此哈希会更改。
  • 父文档的键。
  • 标识从中生成文档的上下文的扩充注释路径。

例如,如果将具有键值“123”的父文档拆分为四页,然后通过索引投影将其中每个页面投影为其自己的文档,则第三页文本的键将类似于“01f07abfe7ed_123_pages_2”。 如果随后更新父文档以添加第五页,则第三页的新键可能是“9d800bdacc0e_123_pages_2”,因为索引器运行之间的随机哈希值发生了变化,即使其余投影数据没有更改也是如此。

更改或添加

如果更改了父文档,使得投影索引文档中的数据发生变化(例如,如果在特定页面更改了一个单词但没有添加新的页面),则目标索引中与该投影对应的数据将会更新以反映该更改。

如果更改了父文档,使得出现了之前不存在的新投影子文档(例如,如果向文档添加了一页或多页的文本),那么这些新的子文档将在下次运行索引器时添加。

在这两种情况下,所有投影文档都会更新,以便在其键中有新的哈希值,无论是否更新了其特定内容。

删除

如果更改了父文档,使得由索引投影生成的子文档不再存在(例如,如果文本缩短,导致区块比之前少),则会删除搜索索引中的相应子文档。 其余子文档还会更新其键以包括新的哈希值,即使其内容不更改也是如此。

如果父文档从数据源中完全删除,则仅当数据源定义上定义的 dataDeletionDetectionPolicy 检测到删除时,才会删除相应的子文档。 如果未配置 dataDeletionDetectionPolicy,但需要从数据源中删除父文档,应在不再需要它时手动删除子文档。