网站被攻击打不开怎么办,大朗做网站的,php手机网站建设,网站主题咋做本文介绍了如何在 Azure SDK for .NET 中使用 C# 和 Azure.Search.Documents客户端库来创建和管理搜索对象。 关注TechLead#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验#xff0c;同济本复旦硕#xff0c;复旦机器人智能实验室… 本文介绍了如何在 Azure SDK for .NET 中使用 C# 和 Azure.Search.Documents客户端库来创建和管理搜索对象。 关注TechLead分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验同济本复旦硕复旦机器人智能实验室成员阿里云认证的资深架构师项目管理专业人士上亿营收AI产品研发负责人。 .NET 的 Azure SDK 库
用于 .NET 的 Azure SDK 包含 Azure SDK 团队提供的一个新的 [Azure.Search.Documents]客户端库该客户端库的功能等同于上一个 [Microsoft.Azure.Search]客户端库。 版本 11 在 Azure 可编程性方面更加一致。
你可以使用此库来执行以下操作
创建和管理搜索索引、数据源、索引器、技能组和同义词映射在索引中加载和管理搜索文档执行查询这些查询全都无需处理 HTTP 和 JSON 的详细信息调用和管理 AI 扩充技能组和输出
此库作为单个 Azure.Search.Documents NuGet 包进行分发其中包括用于以编程方式访问搜索服务的所有 API。
客户端库会定义 SearchIndex、SearchField 和 SearchDocument 之类的类还会定义 SearchIndexClient 和 SearchClient 类中的 SearchIndexClient.CreateIndex 和 SearchClient.Search 之类的操作。
Azure.Search.Documents版本 11面向 2020-06-30 搜索服务规范。
SDK 要求 Visual Studio 2019 或更高版本。 自己的 Azure AI 搜索服务。 要使用 SDK需要服务的名称以及一个或多个 API 密钥。 [在门户中创建一个服务]。 在 Visual Studio 中使用“工具”“NuGet 包管理器”“管理解决方案的 NuGet 包…”下载 Azure.Search.Documents 包。 搜索包名称 Azure.Search.Documents。
用于 .NET 的 Azure SDK 符合 [.NET Standard 2.0]。
示例应用程序
本文“通过示例进行讲授”依赖于 GitHub 上的 DotNetHowTo 代码示例来说明 Azure AI 搜索中的基本概念尤其是如何创建、加载和查询搜索索引。
对于本文的其余部分假定有一个名为“hotels”的新索引该索引中通过对结果进行匹配的多个查询填充了一些文档。
下面是展示总体流程的主程序
// This sample shows how to delete, create, upload documents and query an index
static void Main(string[] args)
{IConfigurationBuilder builder new ConfigurationBuilder().AddJsonFile(appsettings.json);IConfigurationRoot configuration builder.Build();SearchIndexClient indexClient CreateSearchIndexClient(configuration);string indexName configuration[SearchIndexName];Console.WriteLine({0}, Deleting index...\n);DeleteIndexIfExists(indexName, indexClient);Console.WriteLine({0}, Creating index...\n);CreateIndex(indexName, indexClient);SearchClient searchClient indexClient.GetSearchClient(indexName);Console.WriteLine({0}, Uploading documents...\n);UploadDocuments(searchClient);SearchClient indexClientForQueries CreateSearchClientForQueries(indexName, configuration);Console.WriteLine({0}, Run queries...\n);RunQueries(indexClientForQueries);Console.WriteLine({0}, Complete. Press any key to end application...\n);Console.ReadKey();
}接下来是输出的部分屏幕截图假设你使用有效的服务名称和 API 密钥运行此应用程序
客户端类型
客户端库使用三种客户端类型执行各种操作[SearchIndexClient]用于创建、更新或删除索引[SearchClient]用于加载或查询索引[SearchIndexerClient]用于处理索引器和技能组。 本文重点介绍了前两种类型。
所有客户端都至少需要服务名称或终结点以及一个 API 密钥。 通常在配置文件中提供此信息它类似于在 DotNetHowTo 示例应用程序的 appsettings.json 文件中找到的内容。 若要从配置文件中读取数据请将 using Microsoft.Extensions.Configuration; 添加到程序。
下面的语句创建用于创建、更新或删除索引的索引客户端。 它接受服务终结点和管理 API 密钥。
private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
{string searchServiceEndPoint configuration[SearchServiceEndPoint];string adminApiKey configuration[SearchServiceAdminApiKey];SearchIndexClient indexClient new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));return indexClient;
}下一个语句创建用于加载文档或运行查询的搜索客户端。 SearchClient 需要一个索引。 你将需要一个管理 API 密钥来加载文档但可以使用查询 API 密钥来运行查询。
string indexName configuration[SearchIndexName];private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{string searchServiceEndPoint configuration[SearchServiceEndPoint];string queryApiKey configuration[SearchServiceQueryApiKey];SearchClient searchClient new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));return searchClient;
}备注
如果为导入操作提供了无效的密钥例如在其中需要管理密钥的查询密钥则首次调用 SearchClient 上的操作方法时它会引发 CloudException 并显示错误消息“已禁用”。 如果遇到此情况请仔细检查 API 密钥。
删除索引
在早期开发阶段你可能希望包括一个 [DeleteIndex]语句来删除正在执行的索引以便可以使用更新后的定义重新创建它。 Azure AI 搜索的示例代码通常包含一个删除步骤以便你可以重新运行该示例。
下面的行调用 DeleteIndexIfExists
Console.WriteLine({0}, Deleting index...\n);
DeleteIndexIfExists(indexName, indexClient);此方法使用给定的 SearchIndexClient 来检查索引是否存在如果存在则删除该索引
private static void DeleteIndexIfExists(string indexName, SearchIndexClient indexClient)
{try{if (indexClient.GetIndex(indexName) ! null){indexClient.DeleteIndex(indexName);}}catch (RequestFailedException e) when (e.Status 404){// Throw an exception if the index name isnt foundConsole.WriteLine(The index doesnt exist. No deletion occurred.);创建索引
你可以使用 [SearchIndexClient]来创建索引。
以下方法使用 [SearchField]对象的列表创建一个新的 [SearchIndex]对象这些对象定义新索引的架构。 每个字段都有名称、数据类型和数个属性定义其搜索行为。
可以使用 [FieldBuilder]通过模型类来定义字段。 FieldBuilder 类通过检查给定 Hotel 模型类的公共属性和特性使用反射来为索引创建 SearchField 对象的列表。 我们会在以后详细地查看 Hotel 类。
private static void CreateIndex(string indexName, SearchIndexClient indexClient)
{FieldBuilder fieldBuilder new FieldBuilder();var searchFields fieldBuilder.Build(typeof(Hotel));var definition new SearchIndex(indexName, searchFields);indexClient.CreateOrUpdateIndex(definition);
}除了字段之外还可以向索引添加计分配置文件、建议器或 CORS 选项为简洁起见示例中省略了这些参数。 可在 [SearchIndex]属性列表以及 [REST API 参考]中找到有关 SearchIndex 对象及其组成部分的详细信息。
备注
如果需要始终可以直接创建 Field 对象的列表而不是使用 FieldBuilder。 例如你可能不想使用模型类或者可能需要使用不希望通过添加属性来进行修改的现有模型类。
在 Main() 中调用 CreateIndex
Main 通过调用以上方法创建新的“hotels”索引
Console.WriteLine({0}, Creating index...\n);
CreateIndex(indexName, indexClient);使用模型类来表示数据
DotNetHowTo 示例为 Hotel、Address 和 Room 数据结构使用了模型类。 Hotel 引用了 Address一个单一级别的复杂类型多部件字段和 Room多部件字段的集合。
你可以使用这些类型来创建和加载索引以及构建查询的响应
// Use-case: Hotel in a field definition
FieldBuilder fieldBuilder new FieldBuilder();
var searchFields fieldBuilder.Build(typeof(Hotel));// Use-case: Hotel in a response
private static void WriteDocuments(SearchResultsHotel searchResults)
{foreach (SearchResultHotel result in searchResults.GetResults()){Console.WriteLine(result.Document);}Console.WriteLine();
}另一种方法是直接向索引添加字段。 以下示例只显示了几个字段。 SearchIndex index new SearchIndex(indexName){Fields {new SimpleField(hotelId, SearchFieldDataType.String) { IsKey true, IsFilterable true, IsSortable true },new SearchableField(hotelName) { IsFilterable true, IsSortable true },new SearchableField(hotelCategory) { IsFilterable true, IsSortable true },new SimpleField(baseRate, SearchFieldDataType.Int32) { IsFilterable true, IsSortable true },new SimpleField(lastRenovationDate, SearchFieldDataType.DateTimeOffset) { IsFilterable true, IsSortable true }}};字段定义
.NET 中的数据模型及其相应的索引架构应该支持面向最终用户的搜索体验。 .NET 中的每个顶级对象例如搜索索引中的搜索文档对应于在用户界面中显示的搜索结果。 例如在酒店搜索应用程序中最终用户可能想要按酒店名称、酒店特色或特定客房的特征进行搜索。
在每个类中都为字段定义了数据类型和属性属性决定了如何使用该字段。 每个类中的每个公共属性的名称会映射到索引定义中的同名字段。
请看下面的代码片段该代码片段从 Hotel 类中拉取多个字段定义。 请注意Address 和 Rooms 是 C# 类型具有自己的类定义如果要查看它们请参阅示例代码。 这两者都是复杂类型。 有关详细信息请参阅[如何为复杂类型建模]。
public partial class Hotel
{[SimpleField(IsKey true, IsFilterable true)]public string HotelId { get; set; }[SearchableField(IsSortable true)]public string HotelName { get; set; }[SearchableField(AnalyzerName LexicalAnalyzerName.Values.EnLucene)]public string Description { get; set; }[SearchableField(IsFilterable true, IsSortable true, IsFacetable true)]public string Category { get; set; }[JsonIgnore]public bool? SmokingAllowed (Rooms ! null) ? Array.Exists(Rooms, element element.SmokingAllowed true) : (bool?)null;[SearchableField]public Address Address { get; set; }public Room[] Rooms { get; set; }选择字段类
定义字段时你可以使用 [SearchField]基类也可以使用充当“模板”的派生帮助程序模型并使用预配置的属性。
索引中必须恰好有一个字段充当文档键 (IsKey true)。 它必须是字符串并且必须唯一标识每个文档。 它还需要具有 IsHidden true这意味着它在搜索结果中不可见。
添加字段属性
请注意每个字段如何通过属性例如 IsFilterable、IsSortable、IsKey 和 AnalyzerName进行修饰。 这些属性直接映射到 [Azure AI 搜索索引中的相应字段属性]。 FieldBuilder 类使用这些属性来构造索引的字段定义。
字段类型映射
属性的 .NET 类型映射到它们在索引定义中的等效字段类型。 例如Category 字符串属性映射到 Edm.String 类型的 category 字段。 bool? 和 Edm.Boolean、 DateTimeOffset?和 Edm.DateTimeOffset 等之间存在类似的类型映射。
你是否注意到了 SmokingAllowed 属性
[JsonIgnore]
public bool? SmokingAllowed (Rooms ! null) ? Array.Exists(Rooms, element element.SmokingAllowed true) : (bool?)null;此属性的 JsonIgnore 特性告知 FieldBuilder 不要将其序列化为字段形式的索引。 这是创建可在应用程序中用作帮助器的客户端计算属性的极佳方法。 在这种情况下SmokingAllowed 属性将反映 Rooms 集合中的任何 Room 是否允许吸烟。 如果全部为 false则表示整个酒店不允许吸烟。
加载索引
Main 中的下一步会填充新创建的“hotels”索引。 此索引填充操作是通过以下方法完成的为方便演示某些代码已替换为“…”。有关完整的数据填充代码请参阅完整的示例解决方案。
private static void UploadDocuments(SearchClient searchClient)
{IndexDocumentsBatchHotel batch IndexDocumentsBatch.Create(IndexDocumentsAction.Upload(new Hotel(){HotelId 1,HotelName Secret Point Motel,...Address new Address(){StreetAddress 677 5th Ave,...},Rooms new Room[]{new Room(){Description Budget Room, 1 Queen Bed (Cityside),...},new Room(){Description Budget Room, 1 King Bed (Mountain View),...},new Room(){Description Deluxe Room, 2 Double Beds (City View),...}}}),IndexDocumentsAction.Upload(new Hotel(){HotelId 2,HotelName Twin Dome Motel,...{StreetAddress 140 University Town Center Dr,...},Rooms new Room[]{new Room(){Description Suite, 2 Double Beds (Mountain View),...},new Room(){Description Standard Room, 1 Queen Bed (City View),...},new Room(){Description Budget Room, 1 King Bed (Waterfront View),...}}}),IndexDocumentsAction.Upload(new Hotel(){HotelId 3,HotelName Triple Landscape Hotel,...Address new Address(){StreetAddress 3393 Peachtree Rd,...},Rooms new Room[]{new Room(){Description Standard Room, 2 Queen Beds (Amenities),...},new Room (){Description Standard Room, 2 Double Beds (Waterfront View),...},new Room(){Description Deluxe Room, 2 Double Beds (Cityside),...}}}};try{IndexDocumentsResult result searchClient.IndexDocuments(batch);}catch (Exception){// Sometimes when your Search service is under load, indexing will fail for some of the documents in// the batch. Depending on your application, you can take compensating actions like delaying and// retrying. For this simple demo, we just log the failed document keys and continue.Console.WriteLine(Failed to index some of the documents: {0});}Console.WriteLine(Waiting for documents to be indexed...\n);Thread.Sleep(2000);此方法有四个部分。 第一个部分创建包含 3 个 Hotel 对象的数组其中每个对象包含 3 个用作要上传到索引的输入数据的 Room 对象。 为简单起见此数据是硬编码的。 在实际应用中数据有可能会来自 SQL 数据库等外部数据源。
第二部分创建包含文档的 [IndexDocumentsBatch]。 创建 Batch 时指定要应用到 Batch 的操作在这种情况下应调用 [IndexDocumentsAction.Upload]。 然后使用 [IndexDocuments]方法将批处理上传到 Azure AI 搜索索引。
此方法的第三部分是处理索引重要错误情况的 catch 块。 如果你的搜索服务无法为批中的某些文档编制索引则会引发 RequestFailedException。 如果在服务负载过大时为文档编制索引可能会发生异常。 强烈建议在代码中显式处理这种情况。 可以延迟为失败的文档编制索引并重试也可以像此示例一样记录并继续执行还可以执行其他操作具体取决于应用程序对数据一致性的要求。 另一种方法是使用 [SearchIndexingBufferedSender]为失败的索引操作进行智能批处理、自动刷新和重试。 请参阅此示例以了解更多上下文。
最后UploadDocuments 方法延迟了两秒钟。 编制索引在搜索服务中异步进行因此示例应用程序需要等待很短时间以确保文档可用于搜索。 此类延迟通常仅在演示、测试和示例应用程序中是必需的。
在 Main() 中调用 UploadDocuments
下面的代码片段使用 indexClient 的 [GetSearchClient]方法设置 [SearchClient]的实例。 IndexClient 在其请求上使用管理 API 密钥这是加载或刷新文档所必需的。
另一种方法是直接调用 SearchClient 并在 AzureKeyCredential 上传入管理 API 密钥。
SearchClient searchClient indexClient.GetSearchClient(indexName);Console.WriteLine({0}, Uploading documents...\n);
UploadDocuments(searchClient);运行查询
首先设置从 appsettings.json 读取服务终结点和查询 API 密钥的 SearchClient
private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{string searchServiceEndPoint configuration[SearchServiceEndPoint];string queryApiKey configuration[SearchServiceQueryApiKey];SearchClient searchClient new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));return searchClient;
}其次定义发送查询请求的方法。
此方法在每次执行查询时都创建一个新的 [SearchOptions]对象。 此对象用于为查询指定其他选项如排序、筛选、分页和分面。 在此方法中我们为不同的查询设置 Filter、Select 和 OrderBy 属性。 有关搜索查询表达式语法的详细信息请参阅[简单查询语法]。
下一步是查询执行。 使用 SearchClient.Search 方法运行搜索。 对于每个查询请以字符串形式传递要使用的搜索文本或 *如果没有搜索文本以及先前创建的搜索选项。 此外我们指定 Hotel 作为 SearchClient.Search 的类型参数这指示 SDK 将搜索结果中的文档反序列化为类型为 Hotel 的对象。
private static void RunQueries(SearchClient searchClient)
{SearchOptions options;SearchResultsHotel results;Console.WriteLine(Query 1: Search for motel. Return only the HotelName in results:\n);options new SearchOptions();options.Select.Add(HotelName);results searchClient.SearchHotel(motel, options);WriteDocuments(results);Console.Write(Query 2: Apply a filter to find hotels with rooms cheaper than $100 per night, );Console.WriteLine(returning the HotelId and Description:\n);options new SearchOptions(){Filter Rooms/any(r: r/BaseRate lt 100)};options.Select.Add(HotelId);options.Select.Add(Description);results searchClient.SearchHotel(*, options);WriteDocuments(results);Console.Write(Query 3: Search the entire index, order by a specific field (lastRenovationDate) );Console.Write(in descending order, take the top two results, and show only hotelName and );Console.WriteLine(lastRenovationDate:\n);options new SearchOptions(){Size 2};options.OrderBy.Add(LastRenovationDate desc);options.Select.Add(HotelName);options.Select.Add(LastRenovationDate);results searchClient.SearchHotel(*, options);WriteDocuments(results);Console.WriteLine(Query 4: Search the HotelName field for the term hotel:\n);options new SearchOptions();options.SearchFields.Add(HotelName);//Adding details to select, because Location isnt supported yet when deserializing search result to Hoteloptions.Select.Add(HotelId);options.Select.Add(HotelName);options.Select.Add(Description);options.Select.Add(Category);options.Select.Add(Tags);options.Select.Add(ParkingIncluded);options.Select.Add(LastRenovationDate);options.Select.Add(Rating);options.Select.Add(Address);options.Select.Add(Rooms);results searchClient.SearchHotel(hotel, options);WriteDocuments(results);
}第三定义编写响应的方法将每个文档输出到控制台
private static void WriteDocuments(SearchResultsHotel searchResults)
{foreach (SearchResultHotel result in searchResults.GetResults()){Console.WriteLine(result.Document);}Console.WriteLine();
}在 Main() 中调用 RunQueries
SearchClient indexClientForQueries CreateSearchClientForQueries(indexName, configuration);Console.WriteLine({0}, Running queries...\n);
RunQueries(indexClientForQueries);探究查询构造
让我们依次仔细查看每个查询。 下面是用于执行第一个查询的代码
options new SearchOptions();
options.Select.Add(HotelName);results searchClient.SearchHotel(motel, options);WriteDocuments(results);在本例中我们将在任何可搜索字段中搜索“motel”一词的整个索引并且我们只检索 Select 选项指定的酒店名称。 结果如下
Name: Secret Point MotelName: Twin Dome Motel在第二个查询中使用筛选器来选择每晚费用低于 $100 的房间。 在结果中仅返回酒店 ID 和说明
options new SearchOptions()
{Filter Rooms/any(r: r/BaseRate lt 100)
};
options.Select.Add(HotelId);
options.Select.Add(Description);results searchClient.SearchHotel(*, options);以上查询使用 OData $filter 表达式 Rooms/any(r: r/BaseRate lt 100) 来筛选索引中的文档。 这会使用 [any 运算符]将“BaseRate lt 100”应用到 Rooms 集合中的每个项。 有关详细信息请参阅 [OData 筛选器语法]。
在第三个查询中查找最近翻修的前两个酒店并显示酒店名称和上次翻修日期。 代码如下
options new SearchOptions(){Size 2};
options.OrderBy.Add(LastRenovationDate desc);
options.Select.Add(HotelName);
options.Select.Add(LastRenovationDate);results searchClient.SearchHotel(*, options);WriteDocuments(results);在最后一个查询中查找与“motel”一词匹配的所有酒店名称
options.Select.Add(HotelId);
options.Select.Add(HotelName);
options.Select.Add(Description);
options.Select.Add(Category);
options.Select.Add(Tags);
options.Select.Add(ParkingIncluded);
options.Select.Add(LastRenovationDate);
options.Select.Add(Rating);
options.Select.Add(Address);
options.Select.Add(Rooms);results searchClient.SearchHotel(hotel, options);WriteDocuments(results);本部分总结了对 .NET SDK 的介绍但请不要在这里停止。 下一节推荐了一些其他资源便于你详细了解如何使用 Azure AI 搜索进行编程。 关注TechLead分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验同济本复旦硕复旦机器人智能实验室成员阿里云认证的资深架构师项目管理专业人士上亿营收AI产品研发负责人。