快速入门:使用 Azure.Search.Documents 客户端库创建搜索索引Quickstart: Create a search index using the Azure.Search.Documents client library

使用新的 Azure.Search.Documents(版本 11)客户端库以 C# 创建 .NET Core 控制台应用程序,用于创建、加载和查询搜索索引。Use the new Azure.Search.Documents (version 11) client library to create a .NET Core console application in C# that creates, loads, and queries a search index.

下载源代码,从一个已完成的项目着手,或按照本文中的步骤操作,创建自己的项目。Download the source code to start with a finished project or follow the steps in this article to create your own.

备注

正在查找早期版本?Looking for an earlier version? 请转而参阅使用 Microsoft.Azure.Search v10 创建搜索索引See Create a search index using Microsoft.Azure.Search v10 instead.

先决条件Prerequisites

开始之前,需具备以下工具和服务:Before you begin, have the following tools and services:

获取密钥和终结点Get a key and endpoint

对服务的调用要求每个请求都有一个 URL 终结点和一个访问密钥。Calls to the service require a URL endpoint and an access key on every request. 搜索服务是使用这二者创建的,因此,如果向订阅添加了 Azure 认知搜索,则请按以下步骤获取必需信息:A search service is created with both, so if you added Azure Cognitive Search to your subscription, follow these steps to get the necessary information:

  1. 登录到 Azure 门户,在搜索服务的“概述”页中获取 URL。Sign in to the Azure portal, and in your search service Overview page, get the URL. 示例终结点可能类似于 https://mydemo.search.azure.cnAn example endpoint might look like https://mydemo.search.azure.cn.

  2. 在“设置” > “密钥”中,获取管理员密钥以获得针对服务的完全权限,需要该密钥才可创建或删除对象 。In Settings > Keys, get an admin key for full rights on the service, required if you are creating or deleting objects. 有两个可互换的主要密钥和辅助密钥。There are two interchangeable primary and secondary keys. 可以使用其中任意一个。You can use either one.

    获取 HTTP 终结点和访问密钥Get an HTTP endpoint and access key

所有请求对发送到服务的每个请求都需要 API 密钥。All requests require an api-key on every request sent to your service. 具有有效的密钥可以在发送请求的应用程序与处理请求的服务之间建立信任关系,这种信任关系以每个请求为基础。Having a valid key establishes trust, on a per request basis, between the application sending the request and the service that handles it.

设置项目Set up your project

启动 Visual Studio 并新建能在 .NET Core 上运行的控制台应用项目。Start Visual Studio and create a new Console App project that can run on .NET Core.

安装 NuGet 包Install the NuGet package

项目创建后,添加客户端库。After the project is created, add the client library. Azure.Search.Documents 包包含一个客户端库,其中提供了用于与 .NET 中的搜索服务一起使用的所有 API。The Azure.Search.Documents package consists of one client library that provides all of the APIs used to work with a search service in .NET.

  1. 在“工具” > “NuGet 包管理器”中,选择“管理解决方案的 NuGet 包...” 。In Tools > NuGet Package Manager, select Manage NuGet Packages for Solution....

  2. 单击“浏览”。Click Browse.

  3. 搜索 Azure.Search.Documents,并选择 11.0.0 版本。Search for Azure.Search.Documents and select version 11.0.0.

  4. 单击右侧的“安装”,将该程序集添加到你的项目和解决方案。Click Install on the right to add the assembly to your project and solution.

创建搜索客户端Create a search client

  1. 在“Program.cs”中,将命名空间更改为 AzureSearch.SDK.Quickstart.v11,然后添加以下 using 指令。In Program.cs, change the namespace to AzureSearch.SDK.Quickstart.v11 and then add the following using directives.

    using Azure;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    using Azure.Search.Documents.Models;
    
  2. 创建两个客户端:SearchIndexClient 创建索引,SearchClient 使用现有索引。Create two clients: SearchIndexClient creates the index, and SearchClient works with an existing index. 两者都需要服务终结点和管理员 API 密钥才能使用创建/删除权限进行身份验证。Both need the service endpoint and an admin API key for authentication with create/delete rights.

    static void Main(string[] args)
    {
        string serviceName = "<YOUR-SERVICE-NAME>";
        string indexName = "hotels-quickstart-v11";
        string apiKey = "<YOUR-ADMIN-API-KEY>";
    
        // Create a SearchIndexClient to send create/delete index commands
        Uri serviceEndpoint = new Uri($"https://{serviceName}.search.azure.cn/");
        AzureKeyCredential credential = new AzureKeyCredential(apiKey);
        SearchIndexClient idxclient = new SearchIndexClient(serviceEndpoint, credential);
    
        // Create a SearchClient to load and query documents
        SearchClient qryclient = new SearchClient(serviceEndpoint, indexName, credential);
    

1 - 创建索引1 - Create an index

此快速入门生成酒店索引,你将在其中加载酒店数据并对其运行查询。This quickstart builds a Hotels index that you'll load with hotel data and run queries on. 在此步骤中,定义索引中的字段。In this step, define the fields in the index. 每个字段定义都包含名称、数据类型以及确定如何使用该字段的属性。Each field definition includes a name, data type, and attributes that determine how the field is used.

在此示例中,为了简单和可读性,使用了 Azure.Search.Documents 库的同步方法。In this example, synchronous methods of the Azure.Search.Documents library are used for simplicity and readability. 但是,对于生产场景,应使用异步方法来保持应用程序的可缩放性和响应性。However, for production scenarios, you should use asynchronous methods to keep your app scalable and responsive. 例如,使用 CreateIndexAsync,而不是 CreateIndexFor example, you would use CreateIndexAsync instead of CreateIndex.

  1. 向项目添加一个空的类定义:Hotel.csAdd an empty class definition to your project: Hotel.cs

  2. 在“Hotel.cs”中,定义酒店文档的结构。In Hotel.cs, define the structure of a hotel document.

    using System;
    using System.Text.Json.Serialization;
    
    namespace AzureSearch.SDK.Quickstart.v11
    {
        public class Hotel
        {
            [JsonPropertyName("hotelId")]
            public string Id { get; set; }
    
            [JsonPropertyName("hotelName")]
            public string Name { get; set; }
    
            [JsonPropertyName("hotelCategory")]
            public string Category { get; set; }
    
            [JsonPropertyName("baseRate")]
            public Int32 Rate { get; set; }
    
            [JsonPropertyName("lastRenovationDate")]
            public DateTime Updated { get; set; }
        }
    }
    
  3. 在“Program.cs”中,指定字段和属性。In Program.cs, specify the fields and attributes. SearchIndexCreateIndex 用于创建索引。SearchIndex and CreateIndex are used to create an index.

     // Define an index schema using SearchIndex
     // Create the index using SearchIndexClient
     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 }
             }
     };
    
     Console.WriteLine("{0}", "Creating index...\n");
     idxclient.CreateIndex(index);
    

该字段的特性决定字段在应用程序中的使用方式。Attributes on the field determine how it is used in an application. 例如,IsFilterable 属性必须分配给每个支持筛选表达式的字段。For example, the IsFilterable attribute must be assigned to every field that supports a filter expression.

与要求在可搜索字符串字段上使用 IsSearchable 的 .NET SDK 早期版本不同,你可使用 SearchableFieldSimpleField 来简化字段定义。In contrast with previous versions of the .NET SDK that require IsSearchable on searchable string fields, you can use SearchableField and SimpleField to streamline field definitions.

与早期版本类似,定义本身仍需要其他属性。Similar to the previous versions, other attributes are still required on the definition itself. 例如,IsFilterableIsSortableIsFacetable 必须进行显式属性化,如上例中所示。For example, IsFilterable, IsSortable, and IsFacetable must be explicitly attributed, as shown in the sample above.

2 - 加载文档2 - Load documents

Azure 认知搜索对存储在服务中的内容进行搜索。Azure Cognitive Search searches over content stored in the service. 在此步骤中,加载符合刚刚创建的酒店索引的 JSON 文档。In this step, you'll load JSON documents that conform to the hotel index you just created.

在 Azure 认知搜索中,文档这一数据结构既是索引输入,也是查询输出。In Azure Cognitive Search, documents are data structures that are both inputs to indexing and outputs from queries. 文档输入从外部数据源获取,可能是数据库中的行、Blob 存储中的 blob 或磁盘上的 JSON 文档。As obtained from an external data source, document inputs might be rows in a database, blobs in Blob storage, or JSON documents on disk. 在此示例中,我们采用了快捷方式,并在代码本身中嵌入了五个酒店的 JSON 文档。In this example, we're taking a shortcut and embedding JSON documents for five hotels in the code itself.

上传文档时,必须使用 IndexDocumentsBatch 对象。When uploading documents, you must use an IndexDocumentsBatch object. IndexDocumentsBatch 包含操作的集合,其中每个操作均包含一个文档和一个属性,该属性用于指示 Azure 认知搜索要执行什么操作(上传、合并、删除和 mergeOrUpload)。An IndexDocumentsBatch contains a collection of Actions, each of which contains a document and a property telling Azure Cognitive Search what action to perform (upload, merge, delete, and mergeOrUpload).

  1. 在“Program.cs”中,创建文档和索引操作的数组,然后将数组传递给 ndexDocumentsBatch。下面的文档符合宾馆类定义的 hotels-quickstart-v11 索引。In Program.cs, create an array of documents and index actions, and then pass the array to ndexDocumentsBatch The documents below conform to the hotels-quickstart-v11 index, as defined by the hotel class.

    // Load documents (using a subset of fields for brevity)
    IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(new Hotel { Id = "78", Name = "Upload Inn", Category = "hotel", Rate = 279, Updated = new DateTime(2018, 3, 1, 7, 0, 0) }),
        IndexDocumentsAction.Upload(new Hotel { Id = "54", Name = "Breakpoint by the Sea", Category = "motel", Rate = 162, Updated = new DateTime(2015, 9, 12, 7, 0, 0) }),
        IndexDocumentsAction.Upload(new Hotel { Id = "39", Name = "Debug Motel", Category = "motel", Rate = 159, Updated = new DateTime(2016, 11, 11, 7, 0, 0) }),
        IndexDocumentsAction.Upload(new Hotel { Id = "48", Name = "NuGet Hotel", Category = "hotel", Rate = 238, Updated = new DateTime(2016, 5, 30, 7, 0, 0) }),
        IndexDocumentsAction.Upload(new Hotel { Id = "12", Name = "Renovated Ranch", Category = "motel", Rate = 149, Updated = new DateTime(2020, 1, 24, 7, 0, 0) }));
    
    IndexDocumentsOptions idxoptions = new IndexDocumentsOptions { ThrowOnAnyError = true };
    
    Console.WriteLine("{0}", "Loading index...\n");
    qryclient.IndexDocuments(batch, idxoptions);
    

    初始化 IndexDocumentsBatch 对象后,可以通过对 SearchClient 对象调用 IndexDocuments 将其发送到索引。Once you initialize the IndexDocumentsBatch object, you can send it to the index by calling IndexDocuments on your SearchClient object.

  2. 由于这是一个按顺序运行所有命令的控制台应用,因此请在索引和查询之间添加 2 秒的等待时间。Because this is a console app that runs all commands sequentially, add a 2-second wait time between indexing and queries.

    // Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
    Console.WriteLine("Waiting for indexing...\n");
    System.Threading.Thread.Sleep(2000);
    

    2 秒的延迟可对索引编制进行补偿(这是异步操作),这样可在执行查询之前对所有文档编制索引。The 2-second delay compensates for indexing, which is asynchronous, so that all documents can be indexed before the queries are executed. 以延迟方式编写代码通常仅在演示、测试和示例应用程序中是必要的。Coding in a delay is typically only necessary in demos, tests, and sample applications.

3 - 搜索索引3 - Search an index

对第一个文档编制索引后,可立即获取查询结果,但索引的实际测试应等到对所有文档编制索引后进行。You can get query results as soon as the first document is indexed, but actual testing of your index should wait until all documents are indexed.

此部分添加了两个功能:查询逻辑和结果。This section adds two pieces of functionality: query logic, and results. 对于查询,请使用 Search 方法。For queries, use the Search method. 此方法采用搜索文本(查询字符串)以及其他选项This method takes search text (the query string) as well as other options.

SearchResults 类表示结果。The SearchResults class represents the results.

  1. 在“Program.cs”中,创建 WriteDocuments 方法,该方法用于将搜索结果输出到控制台。In Program.cs, create a WriteDocuments method that prints search results to the console.

    private static void WriteDocuments(SearchResults<Hotel> searchResults)
    {
        foreach (SearchResult<Hotel> response in searchResults.GetResults())
        {
            Hotel doc = response.Document;
            var score = response.Score;
            Console.WriteLine($"Name: {doc.Name}, Type: {doc.Category}, Rate: {doc.Rate}, Last-update: {doc.Updated}, Score: {score}");
        }
    
        Console.WriteLine();
    }
    
  2. 创建 RunQueries 方法,该方法用于执行查询并返回结果。Create a RunQueries method to execute queries and return results. 结果是 Hotel 对象。Results are Hotel objects.

    private static void RunQueries(SearchClient qryclient)
    {
        SearchOptions options;
        SearchResults<Hotel> response;
    
        Console.WriteLine("Query #1: Search on the term 'motel' and list the relevance score for each match...\n");
    
        options = new SearchOptions()
        {
            Filter = "",
            OrderBy = { "" }
        };
    
        response = qryclient.Search<Hotel>("motel", options);
        WriteDocuments(response);
    
        Console.WriteLine("Query #2: Find hotels where 'type' equals hotel...\n");
    
        options = new SearchOptions()
        {
            Filter = "hotelCategory eq 'hotel'",
        };
    
        response = qryclient.Search<Hotel>("*", options);
        WriteDocuments(response);
    
        Console.WriteLine("Query #3: Filter on rates less than $200 and sort by when the hotel was last updated...\n");
    
        options = new SearchOptions()
        {
            Filter = "baseRate lt 200",
            OrderBy = { "lastRenovationDate desc" }
        };
    
        response = qryclient.Search<Hotel>("*", options);
        WriteDocuments(response);
    }
    

此示例展示两种在查询中匹配术语的方法:全文搜索和筛选器:This example shows the two ways of matching terms in a query: full-text search, and filters:

  • 全文搜索会在索引的可搜索字段中查询一个或多个术语。Full-text search queries for one or more terms in searchable fields in your index. 第一个查询是全文搜索。The first query is full text search. 全文搜索生成用于对结果进行排序的相关性分数。Full-text search produces relevance scores used to rank the results.

  • 筛选器是布尔表达式,该表达式通过索引中的 IsFilterable 字段求值。Filter is a boolean expression that is evaluated over IsFilterable fields in an index. 筛选器查询包括或排除值。Filter queries either include or exclude values. 同样,筛选器查询没有关联的相关性分数。As such, there is no relevance score associated with a filter query. 最后两个查询演示筛选器搜索。The last two queries demonstrate filter search.

可以配合使用全文搜索和筛选器,也可以单独使用。You can use full-text search and filters together or separately.

使用 SearchClient.Search 方法可同时执行搜索和查询。Both searches and filters are performed using the SearchClient.Search method. 搜索查询可在 searchText 字符串中传递,而筛选表达式则可在 SearchOptions 类的 Filter 属性中传递。A search query can be passed in the searchText string, while a filter expression can be passed in the Filter property of the SearchOptions class. 若要筛选但不搜索,只需传递 "*" 作为 Search 方法的 searchText 参数。To filter without searching, just pass "*" for the searchText parameter of the Search method. 若要搜索但不筛选,则不设置 Filter 属性,或不在 SearchOptions 实例中传递。To search without filtering, leave the Filter property unset, or do not pass in a SearchOptions instance at all.

运行程序Run the program

按 F5 可重新生成应用并完整运行该程序。Press F5 to rebuild the app and run the program in its entirety.

输出包含 Console.WriteLIne 中的消息,并添加了查询信息和结果。Output includes messages from Console.WriteLIne, with the addition of query information and results.

清理资源Clean up resources

在自己的订阅中操作时,最好在项目结束时确定是否仍需要已创建的资源。When you're working in your own subscription, it's a good idea at the end of a project to identify whether you still need the resources you created. 持续运行资源可能会产生费用。Resources left running can cost you money. 可以逐个删除资源,也可以删除资源组以删除整个资源集。You can delete resources individually or delete the resource group to delete the entire set of resources.

可以使用左侧导航窗格中的“所有资源”或“资源组”链接 ,在门户中查找和管理资源。You can find and manage resources in the portal, using the All resources or Resource groups link in the left-navigation pane.

如果使用的是免费服务,请记住只能设置三个索引、索引器和数据源。If you are using a free service, remember that you are limited to three indexes, indexers, and data sources. 可以在门户中删除单个项目,以不超出此限制。You can delete individual items in the portal to stay under the limit.

后续步骤Next steps

在此 C# 快速入门中,你已完成一系列任务,即创建索引、使用文档加载索引并运行查询。In this C# quickstart, you worked through a series of tasks to create an index, load it with documents, and run queries. 在不同的阶段,我们采用快捷方式来简化代码,从而实现可读性和可理解性。At different stages, we took shortcuts to simplify the code for readability and comprehension. 如果你已理解这些基本概念,我们建议阅读下一篇文章,探索替代方法和概念,进一步加深你的理解。If you are comfortable with the basic concepts, we recommend the next article for an exploration of alternative approaches and concepts that will deepen your knowledge.