教程:使用 .NET SDK 为 Azure SQL 数据编制索引

配置一个索引器,用于从 Azure SQL 数据库提取可搜索的数据,从而将其发送到 Azure AI 搜索中的搜索索引。

本教程使用 C# 和适用于 .NET 的 Azure SDK 执行以下任务:

  • 创建连接到 Azure SQL 数据库的数据源
  • 创建索引器
  • 运行索引器以将数据载入索引
  • 以验证步骤的形式查询索引

如果没有 Azure 订阅,请在开始前创建一个试用版订阅

先决条件

注意

可在本教程中使用免费搜索服务。 免费层限制为三个索引、三个索引器和三个数据源。 本教程每样创建一个。 在开始之前,请确保服务中有足够的空间可接受新资源。

下载文件

本教程的源代码位于 Azure-Samples/search-dotnet-getting-started GitHub 存储库中的 DotNetHowToIndexer 文件夹内。

1 - 创建服务

本教程使用 Azure AI 搜索进行索引编制和查询,使用 Azure SQL 数据库作为外部数据源。 如果可能,请在同一区域和资源组中创建这两个服务,使它们相互靠近并易于管理。 在实践中,Azure SQL 数据库可以位于任意区域中。

从 Azure SQL 数据库开始

本教程在示例下载中提供了 hotels.sql 文件来填充数据库。 Azure AI 搜索使用平展行集,例如从视图或查询生成的行集。 示例解决方案中的 SQL 文件创建并填充单个表。

如果你有现有的 Azure SQL 数据库资源,可在其中添加 hotels 表,从“打开查询”步骤开始。

  1. 使用快速入门:创建单一数据库中的说明创建 Azure SQL 数据库。

    数据库的服务器配置很重要。

    • 选择提示你指定用户名和密码的 SQL Server 身份验证选项。 索引器使用的 ADO.NET 连接字符串需要用到它。

    • 选择一个公共连接。 它会使本教程更易于完成。 不建议将公共连接用于生产,建议在本教程结束时删除此资源

    服务器配置的屏幕截图。

  2. 在 Azure 门户中,转到新资源。

  3. 使用快速入门:在 Azure 门户中创建服务器级防火墙规则中的说明添加防火墙规则以允许从你的客户端访问。 可以从命令提示符运行 ipconfig 以获取你的 IP 地址。

  4. 使用查询编辑器加载示例数据。 在导航窗格中,选择“查询编辑器(预览版)”并输入服务器管理员的用户名和密码。

    如果收到访问被拒错误,请从错误消息复制客户端 IP 地址,打开服务器的网络安全页,然后添加允许从你的客户端访问的入站规则。

  5. 在查询编辑器中选择“打开查询”,然后在本地计算机上导航到 hotels.sql 文件所在的位置。

  6. 选择该文件,然后选择“打开”。 此脚本应与以下屏幕截图类似:

    屏幕截图显示查询编辑器窗口中的 SQL 脚本。

  7. 选择“运行”以执行查询。 在“结果”窗格中,应会看到一条三行内容的消息,指示查询成功。

  8. 若要从此表返回一个行集,可执行以下充当验证步骤的查询:

    SELECT * FROM Hotels
    
  9. 复制数据库的 ADO.NET 连接字符串 在“设置”>“连接字符串”下,复制类似于以下示例的 ADO.NET 连接字符串。

    Server=tcp:{your_dbname}.database.chinacloudapi.cn,1433;Initial Catalog=hotels-db;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
    

在下一篇有关设置环境的练习中,需要用到此连接字符串。

下一个组件是可以在门户中创建的 Azure AI 搜索。 可使用免费层完成本演练。

API 调用需要服务 URL 和访问密钥。 搜索服务是使用这二者创建的,因此,如果向订阅添加了 Azure AI 搜索,则请按以下步骤获取必需信息:

  1. 登录到 Azure 门户,在搜索服务的“概览”页中获取 URL。 示例终结点可能类似于 https://mydemo.search.azure.cn

  2. 在“设置”>“密钥”中,获取有关该服务的完全权限的管理员密钥 。 有两个可交换的管理员密钥,为保证业务连续性而提供,以防需要滚动一个密钥。 可以在请求中使用主要或辅助密钥来添加、修改和删除对象。

    Azure 门户页面的屏幕截图,其中显示了搜索服务的 HTTP 终结点和访问密钥位置。

2 - 设置环境

  1. 启动 Visual Studio 并打开 DotNetHowToIndexers.sln

  2. 在解决方案资源管理器中,打开“appsettings.json”以提供连接信息。

  3. 对于 SearchServiceEndPoint,如果服务概述页面上的完整 URL 为“https://my-demo-service.search.azure.cn"”,则要提供的值为整个 URL。

  4. 对于 AzureSqlConnectionString,字符串格式如下所示:"Server=tcp:{your_dbname}.database.chinacloudapi.cn,1433;Initial Catalog=hotels-db;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"

    {
      "SearchServiceEndPoint": "<placeholder-search-full-url>",
      "SearchServiceAdminApiKey": "<placeholder-admin-key-for-search-service>",
      "AzureSqlConnectionString": "<placeholder-ADO.NET-connection-string",
    }
    
  5. 将 SQL 连接字符串中的用户密码替换为有效的密码。 数据库名称和用户名可以复制,但密码必须手动输入。

3 - 创建管道

索引器需要数据源对象和索引。 相关代码在两个文件中:

  • hotel.cs,包含定义索引的架构

  • Program.cs,包含用于创建和管理服务中的结构的函数

在 hotel.cs 中

索引架构定义字段集合,包含的属性用于指定允许的操作,例如字段是否可以进行全文搜索、筛选或排序,如以下针对 HotelName 的字段定义所示。 SearchableField 按定义进行全文搜索。 其他属性是显式分配的。

. . . 
[SearchableField(IsFilterable = true, IsSortable = true)]
[JsonPropertyName("hotelName")]
public string HotelName { get; set; }
. . .

架构还可以包含其他元素,包括用于提高搜索得分的计分配置文件、自定义分析器和其他构造。 但对于我们来说,架构只需进行稀疏定义,只包含在示例数据集中发现的字段。

在 Program.cs 中

主程序包含用于创建索引器客户端、索引、数据源和索引器的逻辑。 此代码检查是否存在同一名称的资源,如果存在则会将其删除,所依据的假设是此程序可能多次运行。

数据源对象是使用特定于 Azure SQL 数据库资源的设置配置的,其中包括部分或增量索引,用于使用 Azure SQL 的内置更改检测功能。 Azure SQL 中的 hotels 源演示数据库包含一个名为 IsDeleted 的“软删除”列。 如果在数据库中将此列设置为 true,则索引器会从 Azure AI 搜索索引中删除相应的文档。

Console.WriteLine("Creating data source...");

var dataSource =
      new SearchIndexerDataSourceConnection(
         "hotels-sql-ds",
         SearchIndexerDataSourceType.AzureSql,
         configuration["AzureSQLConnectionString"],
         new SearchIndexerDataContainer("hotels"));

indexerClient.CreateOrUpdateDataSourceConnection(dataSource);

索引器对象与平台无关,无论源是什么,配置、计划和调用都是相同的。 此示例索引器包含一个计划和一个用于清除索引器历史记录的重置选项,并调用一个方法来创建和立即运行索引器。 若要创建或更新索引器,请使用 CreateOrUpdateIndexerAsync

Console.WriteLine("Creating Azure SQL indexer...");

var schedule = new IndexingSchedule(TimeSpan.FromDays(1))
{
      StartTime = DateTimeOffset.Now
};

var parameters = new IndexingParameters()
{
      BatchSize = 100,
      MaxFailedItems = 0,
      MaxFailedItemsPerBatch = 0
};

// Indexer declarations require a data source and search index.
// Common optional properties include a schedule, parameters, and field mappings
// The field mappings below are redundant due to how the Hotel class is defined, but 
// we included them anyway to show the syntax 
var indexer = new SearchIndexer("hotels-sql-idxr", dataSource.Name, searchIndex.Name)
{
      Description = "Data indexer",
      Schedule = schedule,
      Parameters = parameters,
      FieldMappings =
      {
         new FieldMapping("_id") {TargetFieldName = "HotelId"},
         new FieldMapping("Amenities") {TargetFieldName = "Tags"}
      }
};

await indexerClient.CreateOrUpdateIndexerAsync(indexer);

索引器运行通常是有计划的,但在开发期间,你可能想要立即使用 RunIndexerAsync 运行索引器。

Console.WriteLine("Running Azure SQL indexer...");

try
{
      await indexerClient.RunIndexerAsync(indexer.Name);
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
      Console.WriteLine("Failed to run indexer: {0}", ex.Message);
}

4 - 生成解决方案

按 F5 生成并运行解决方案。 程序在调试模式下执行。 控制台窗口报告每项操作的状态。

屏幕截图显示程序的控制台输出。

代码将在 Visual Studio 本地运行,连接到 Azure 中的搜索服务,后者又会连接到 Azure SQL 数据库并检索数据集。 由于此处会发生多项操作,因此可能会造成多个故障点。 如果遇到错误,请先检查以下条件:

  • 你提供的搜索服务连接信息是完整的 URL。 如果只输入了服务名,则操作会停在索引创建阶段,出现“无法连接”错误。

  • appsettings.json 中的数据库连接信息。 它应该是从门户获得的 ADO.NET 连接字符串,经修改后包括了适用于数据库的用户名和密码。 用户帐户必须有权检索数据。 你的本地客户端 IP 地址必须能够通过防火墙进行入站访问。

  • 资源限制。 回想一下,免费层仅限三个索引、索引器和数据源。 达到最大限制的服务不能创建新的对象。

使用 Azure 门户验证对象的创建,然后使用“搜索资源管理器”查询索引。

  1. 登录到 Azure 门户,在你的搜索服务左导航窗格中,轮流打开每个页面,以验证对象是否已创建。 索引索引器数据源将分别具有“hotels-sql-idx”、“hotels-sql-indexer”和“hotels-sql-ds”。

  2. 在“索引”选项卡上,选择 hotels-sql-idx 索引。 在 hotels 页上,“搜索资源管理器”是第一个选项卡。

  3. 选择“搜索”,发出空查询。

    索引中的三个条目以 JSON 文档的形式返回。 搜索浏览器返回 JSON 格式的文档,方便你查看整个结构。

    目标索引的搜索浏览器查询的屏幕截图。

  4. 接下来,切换到 JSON 视图,以便输入查询参数:

    {
         "search": "river",
         "count": true
    }
    

    此查询调用 river 一词的全文搜索,结果包含匹配文档的计数。 在索引很大且文档成千上万甚至数百万的测试方案中,返回匹配文档的计数很有用。 在本示例中,只有一个文档与查询匹配。

  5. 最后,输入将搜索结果限定为感兴趣的字段的参数:

    {
         "search": "river",
         "select": "hotelId, hotelName, baseRate, description",
         "count": true
    }
    

    查询响应范围缩小为选定字段,使输出更简洁。

重置并重新运行

在开发的前期试验阶段,设计迭代的最实用方法是,删除 Azure AI 搜索中的对象,并允许代码重新生成它们。 资源名称是唯一的。 删除某个对象后,可以使用相同的名称重新创建它。

本教程的示例代码将检查现有对象并将其删除,使你能够重新运行代码。

也可以使用门户来删除索引、索引器和数据源。

清理资源

在自己的订阅中操作时,最好在项目结束时删除不再需要的资源。 持续运行资源可能会产生费用。 可以逐个删除资源,也可以删除资源组以删除整个资源集。

可以使用左侧导航窗格中的“所有资源”或“资源组”链接 ,在门户中查找和管理资源。

后续步骤

熟悉 SQL 数据库索引编制的基础知识后,接下来让我们更详细地了解索引器配置。