分享方式:


快速入門:使用 Azure SDK 進行全文檢索搜尋

了解如何使用 Azure SDK 中的 Azure.Search.Documents 用戶端程式庫,以使用全文搜索的範例資料來建立、載入及查詢搜尋索引。 全文搜索會使用 Apache Lucene 來編制索引和查詢,並使用 BM25 排名演算法來評分結果。

本快速入門提供下列 SDK 的步驟:

必要條件

  • 具有有效訂用帳戶的 Azure 帳戶。 您可以免費建立帳戶

  • 一項 Azure AI 搜尋服務。 如果您沒有服務,請建立服務。 您可以使用免費服務層級來進行本快速入門。

  • 服務的 API 金鑰和服務端點。 登入 Azure 入口網站,然後尋找您的搜尋服務

    在 [概觀]段中,複製 URL 並將其儲存至文本編輯器,以供後續步驟使用。 範例端點看起來會像是 https://mydemo.search.windows.net

    在 [ 設定>金鑰 ] 區段中,複製並儲存系統管理金鑰,以取得建立和刪除物件的完整許可權。 共有兩個可交換的主要和次要金鑰。 選擇任一個。

    顯示 HTTP 端點和主要和次要 API 金鑰位置的螢幕快照。

建立、載入,以及查詢索引

選擇下一個步驟的程式設計語言。 Azure.Search.Documents 用戶端連結庫適用於 .NET、Python、Java 和 JavaScript/Typescript 的 Azure SDK 中提供。

使用 Azure.Search.Documents 用戶端程式庫建置主控台應用程式,以建立、載入及查詢搜尋索引。

或者,您可以下載原始程式碼以使用已完成的專案來開始,或遵循這些步驟來建立您自己的程式碼。

設定您的環境

  1. 啟動 Visual Studio 並建立主控台應用程式的新專案。

  2. 在 [工具]>[NuGet 套件管理員] 中,選取 [管理解決方案的 NuGet 套件] 中。

  3. 選取瀏覽

  4. 搜尋 Azure.Search.Documents 套件,然後選取 11.0 版或更新版本。

  5. 選取 [安裝] 以將組件新增到您的專案與解決方案。

建立搜尋用戶端

  1. Program.cs 中,將命名空間變更為 AzureSearch.SDK.Quickstart.v11,然後新增下列 using 指示詞。

    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 會載入並查詢現有的索引。 兩者都需要服務端點和管理員 API 金鑰,以使用 create/delete 權限進行驗證。

    因為程式代碼會為您建置 URI,請在 屬性中 serviceName 只指定搜尋服務名稱。

     static void Main(string[] args)
     {
         string serviceName = "<your-search-service-name>";
         string apiKey = "<your-search-service-admin-api-key>";
         string indexName = "hotels-quickstart";
    
         // Create a SearchIndexClient to send create/delete index commands
         Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
         AzureKeyCredential credential = new AzureKeyCredential(apiKey);
         SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
    
         // Create a SearchClient to load and query documents
         SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, credential);
         . . . 
     }
    

建立索引

本快速入門會建置供您隨著飯店資料一起載入並對其執行查詢的 Hotels 索引。 在此步驟中,請定義索引中的欄位。 每個欄位定義都包含名稱、資料類型和屬性,以決定欄位的使用方式。

在此範例中,Azure.Search.Documents 連結庫的同步方法會用於簡單且易讀性。 不過,在生產案例中,則請使用非同步方法,以讓應用程式保持可調整和能回應的狀態。 例如,使用 CreateIndexAsync 而非 CreateIndex

  1. 將空的類別定義新增至專案中:Hotel.cs

  2. 將下列程式碼複製到 Hotel.cs ,以定義飯店文件的結構。 欄位上的屬性決定它如何在應用程式中使用。 例如,必須將 IsFilterable 屬性指派給支援篩選條件運算式的每個欄位。

    using System;
    using System.Text.Json.Serialization;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    
    namespace AzureSearch.Quickstart
    {
        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(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
            [JsonPropertyName("Description_fr")]
            public string DescriptionFr { get; set; }
    
            [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public string Category { get; set; }
    
            [SearchableField(IsFilterable = true, IsFacetable = true)]
            public string[] Tags { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public bool? ParkingIncluded { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public DateTimeOffset? LastRenovationDate { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public double? Rating { get; set; }
    
            [SearchableField]
            public Address Address { get; set; }
        }
    }
    

    Azure.Search.Documents 用戶端連結庫中,您可以使用 SearchableField 和 SimpleField 來簡化欄位定義。 兩者都是 SearchField 的衍生項目,而且可能會簡化您的程式碼:

    • SimpleField 可以是任何資料類型、一律不可搜尋 (全文檢索搜尋查詢會將其忽略),以及可擷取 (不會隱藏)。 其他屬性預設為關閉,但可以啟用。 您可以針對僅用於篩選、Facet 或評分設定檔的文件識別碼或欄位使用 SimpleField。 若是如此,請務必套用案例所需的任何屬性,例如文件識別碼的 IsKey = true。 如需詳細資訊,請參閱原始程式碼中的 SimpleFieldAttribute.cs

    • SearchableField 必須是字串,而且一律可搜尋並可擷取。 其他屬性預設為關閉,但可以啟用。 因為此欄位類型是可搜尋,所以其支援同義字和分析器屬性的完整補語。 如需詳細資訊,請參閱原始程式碼中的 SearchableFieldAttribute.cs

    無論您使用的是基本 SearchField API 或其中一個 協助程式模型,都必須明確啟用篩選、Facet 和排序屬性。 例如,IsFilterable、IsSortableIsFacetable 必須明確屬性化,如上一個範例所示。

  3. 將第二個空的類別定義新增至專案:Address.cs。 將下列程式碼複製到類別中。

    using Azure.Search.Documents.Indexes;
    
     namespace AzureSearch.Quickstart
     {
         public partial class Address
         {
             [SearchableField(IsFilterable = true)]
             public string StreetAddress { get; set; }
    
             [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
             public string City { get; set; }
    
             [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
             public string StateProvince { get; set; }
    
             [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
             public string PostalCode { get; set; }
    
             [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
             public string Country { get; set; }
         }
     }
    
  4. 再建立兩個類別: Hotel.Methods.csAddress.Methods.csToString() 寫。 這些類別是用來在主控台輸出中呈現搜尋結果。 本文並未提供這些類別的內容,但您可以從 GitHub 中的檔案複製程式碼。

  5. Program.cs 中,建立 SearchIndex 物件,然後呼叫 CreateIndex 方法來表示搜尋服務中的索引。 索引也包含 SearchSuggester,可在指定的欄位上啟用自動完成功能。

     // Create hotels-quickstart index
     private static void CreateIndex(string indexName, SearchIndexClient adminClient)
     {
         FieldBuilder fieldBuilder = new FieldBuilder();
         var searchFields = fieldBuilder.Build(typeof(Hotel));
    
         var definition = new SearchIndex(indexName, searchFields);
    
         var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
         definition.Suggesters.Add(suggester);
    
         adminClient.CreateOrUpdateIndex(definition);
     }
    

載入文件

Azure AI 搜尋服務會搜尋服務中儲存的內容。 在此步驟中,您會載入與剛建立的飯店索引相符的 JSON 文件。

在 Azure AI 搜尋服務中,搜尋文件是同時屬於索引輸入與查詢輸出的資料結構。 如同從外部資料來源所取得的一樣,文件輸入可能是資料庫中的資料列,Blob 儲存體中的 Blob 或磁碟上的 JSON 文件。 在此範例中,我們採用捷徑,並針對程式碼本身中的四家旅館內嵌 JSON 文件。

上傳文件時,您必須使用 IndexDocumentsBatch 物件。 IndexDocumentsBatch 物件包含動作集合,每個物件都包含文件與屬性,後者會告知 Azure AI 搜尋服務所應執行的動作 (上傳、合併、刪除及 mergeOrUpload)。

  1. Program.cs 中,建立文件與索引動作的索引,然後將該陣列傳遞到 IndexDocumentsBatch。 下列檔符合 hotels-quickstart 索引,如旅館類別所定義。

    // Upload documents in a single Upload request.
    private static void UploadDocuments(SearchClient searchClient)
    {
        IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
            IndexDocumentsAction.Upload(
                new Hotel()
                {
                    HotelId = "1",
                    HotelName = "Stay-Kay City Hotel",
                    Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                    DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
                    Category = "Boutique",
                    Tags = new[] { "pool", "air conditioning", "concierge" },
                    ParkingIncluded = false,
                    LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
                    Rating = 3.6,
                    Address = new Address()
                    {
                        StreetAddress = "677 5th Ave",
                        City = "New York",
                        StateProvince = "NY",
                        PostalCode = "10022",
                        Country = "USA"
                    }
                }),
            IndexDocumentsAction.Upload(
                new Hotel()
                {
                    HotelId = "2",
                    HotelName = "Old Century Hotel",
                    Description = "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
                    DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                    Category = "Boutique",
                    Tags = new[] { "pool", "free wifi", "concierge" },
                    ParkingIncluded = false,
                    LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero),
                    Rating = 3.60,
                    Address = new Address()
                    {
                        StreetAddress = "140 University Town Center Dr",
                        City = "Sarasota",
                        StateProvince = "FL",
                        PostalCode = "34243",
                        Country = "USA"
                    }
                }),
            IndexDocumentsAction.Upload(
                new Hotel()
                {
                    HotelId = "3",
                    HotelName = "Gastronomic Landscape Hotel",
                    Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                    DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                    Category = "Resort and Spa",
                    Tags = new[] { "air conditioning", "bar", "continental breakfast" },
                    ParkingIncluded = true,
                    LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
                    Rating = 4.80,
                    Address = new Address()
                    {
                        StreetAddress = "3393 Peachtree Rd",
                        City = "Atlanta",
                        StateProvince = "GA",
                        PostalCode = "30326",
                        Country = "USA"
                    }
                }),
            IndexDocumentsAction.Upload(
                new Hotel()
                {
                    HotelId = "4",
                    HotelName = "Sublime Palace Hotel",
                    Description = "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
                    DescriptionFr = "Le Sublime Palace Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Palace fait partie d'un Palace 1800 restauré avec amour.",
                    Category = "Boutique",
                    Tags = new[] { "concierge", "view", "24-hour front desk service" },
                    ParkingIncluded = true,
                    LastRenovationDate = new DateTimeOffset(1960, 2, 06, 0, 0, 0, TimeSpan.Zero),
                    Rating = 4.60,
                    Address = new Address()
                    {
                        StreetAddress = "7400 San Pedro Ave",
                        City = "San Antonio",
                        StateProvince = "TX",
                        PostalCode = "78216",
                        Country = "USA"
                    }
                })
            );
    
        try
        {
            IndexDocumentsResult result = searchClient.IndexDocuments(batch);
        }
        catch (Exception)
        {
            // If for some reason any documents are dropped during indexing, you can compensate by delaying and
            // retrying. This simple demo just logs the failed document keys and continues.
            Console.WriteLine("Failed to index some of the documents: {0}");
        }
    }
    

    一旦將 IndexDocumentsBatch 物件初始化之後,您就可以將其傳送至索引,方法是在 SearchClient 物件上呼叫 IndexDocuments

  2. 將下列數行新增至 Main()。 載入文件是使用 SearchClient 來完成,但作業也需要服務的管理員權限,這通常與 SearchIndexClient 相關聯。 設定此作業的其中一種方式是透過 取得 SearchClient SearchIndexClientadminClient 在此範例中)。

     SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
    
     // Load documents
     Console.WriteLine("{0}", "Uploading documents...\n");
     UploadDocuments(ingesterClient);
    
  3. 因為這是會循序執行所有命令的主控台應用程式,因此請在索引編製和查詢之間新增 2 秒的等候時間。

    // 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 秒延的遲是針對索引編製進行補償,這是非同步作業,因此可以在執行查詢之前針對所有文件編製索引。 設計延遲程式碼只有在示範、測試與範例應用程式中才有必要。

搜尋索引

您可以在系統為第一個文件編製索引之後立即取得結果,但索引的實際測試應該等到系統為所有文件編製索引之後才進行。

此節新增兩個功能:查詢邏輯,以及結果。 針對查詢,請使用搜尋方法。 這個方法會接受搜尋文字 (查詢字串) 和其他選項

SearchResults 類別代表結果。

  1. Program.cs中,建立將 WriteDocuments 搜尋結果列印至控制台的方法。

    // Write search results to console
    private static void WriteDocuments(SearchResults<Hotel> searchResults)
    {
        foreach (SearchResult<Hotel> result in searchResults.GetResults())
        {
            Console.WriteLine(result.Document);
        }
    
        Console.WriteLine();
    }
    
    private static void WriteDocuments(AutocompleteResults autoResults)
    {
        foreach (AutocompleteItem result in autoResults.Results)
        {
            Console.WriteLine(result.Text);
        }
    
        Console.WriteLine();
    }
    
  2. 建立 RunQueries 方法以執行查詢並傳回結果。 結果是 Hotel 物件。 這個範例會顯示方法簽章和第一個查詢。 此查詢會示範可讓您使用文件。中選取的欄位來撰寫結果的 Select 參數。

    // Run queries, use WriteDocuments to print output
    private static void RunQueries(SearchClient srchclient)
    {
        SearchOptions options;
        SearchResults<Hotel> response;
    
        // Query 1
        Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
    
        options = new SearchOptions()
        {
            IncludeTotalCount = true,
            Filter = "",
            OrderBy = { "" }
        };
    
        options.Select.Add("HotelId");
        options.Select.Add("HotelName");
        options.Select.Add("Address/City");
    
        response = srchclient.Search<Hotel>("*", options);
        WriteDocuments(response);
    
  3. 在第二個查詢中,搜尋字詞、新增篩選,以選取評分大於 4 的文件 ,然後依遞減順序依評分 排序。 篩選則是布林運算式,會針對索引中的 IsFilterable 欄位來進行評估。 篩選會查詢包含或排除值。 因此,沒有與篩選查詢相關聯的相關性分數。

    // Query 2
    Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
    
    options = new SearchOptions()
    {
        Filter = "Rating gt 4",
        OrderBy = { "Rating desc" }
    };
    
    options.Select.Add("HotelId");
    options.Select.Add("HotelName");
    options.Select.Add("Rating");
    
    response = srchclient.Search<Hotel>("hotels", options);
    WriteDocuments(response);
    
  4. 第三個查詢示範 searchFields,此參數用來將全文檢索搜尋作業的範圍限定為特定欄位。

    // Query 3
    Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n");
    
    options = new SearchOptions()
    {
        SearchFields = { "Tags" }
    };
    
    options.Select.Add("HotelId");
    options.Select.Add("HotelName");
    options.Select.Add("Tags");
    
    response = srchclient.Search<Hotel>("pool", options);
    WriteDocuments(response);
    
  5. 第四個查詢示範 facets,可用來建構多面向導覽結構。

     // Query 4
     Console.WriteLine("Query #4: Facet on 'Category'...\n");
    
     options = new SearchOptions()
     {
         Filter = ""
     };
    
     options.Facets.Add("Category");
    
     options.Select.Add("HotelId");
     options.Select.Add("HotelName");
     options.Select.Add("Category");
    
     response = srchclient.Search<Hotel>("*", options);
     WriteDocuments(response);
    
  6. 在第五個查詢中,傳回特定的文件。 檔查閱是結果集中事件的典型回應 OnClick

     // Query 5
     Console.WriteLine("Query #5: Look up a specific document...\n");
    
     Response<Hotel> lookupResponse;
     lookupResponse = srchclient.GetDocument<Hotel>("3");
    
     Console.WriteLine(lookupResponse.Value.HotelId);
    
  7. 最後一個查詢會顯示自動完成的語法,模擬sa的部分使用者輸入,其解析為與索引中定義之建議工具相關聯的sourceFields中兩個可能的相符專案。

     // Query 6
     Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
    
     var autoresponse = srchclient.Autocomplete("sa", "sg");
     WriteDocuments(autoresponse);
    
  8. RunQueries 加入 Main()

    // Call the RunQueries method to invoke a series of queries
    Console.WriteLine("Starting queries...\n");
    RunQueries(srchclient);
    
    // End the program
    Console.WriteLine("{0}", "Complete. Press any key to end this program...\n");
    Console.ReadKey();
    

先前的查詢會顯示在查詢中比對字詞的多種方式:全文檢索搜尋、篩選和自動完成。

全文搜索搜尋和篩選都會使用 SearchClient.Search 方法來執行。 搜尋查詢可以在 searchText 字串中傳遞,而篩選運算式則可以在 SearchOptions 類別的篩選屬性中傳遞。 若要篩選而不進行搜尋,只要針對搜尋方法的 searchText 參數傳遞 "*" 即可。 若要在不進行篩選的情況下搜尋,則請將 Filter 屬性保留在未設定狀態,或完全不要傳入 SearchOptions 執行個體。

執行程式

F5 重建應用程式,並完整執行程式。

輸出中包含來自 Console.WriteLine 的訊息,並且會加上查詢資訊和結果。

清除資源

如果您是在自己的訂用帳戶中進行,建議您在專案結束時判斷自己是否仍需要先前所建立的資源。 資源若繼續執行,將需付費。 您可以個別刪除資源,或刪除資源群組以刪除整組資源。

您可以使用左導覽窗格中的 [所有資源] 或 [資源群組] 連結,在入口網站中尋找和管理資源。

如果您使用免費服務,請記住您會有三個索引、索引子和資料來源的限制。 您可以在入口網站中刪除個別項目,以避免超出限制。

後續步驟

在此快速入門中,您已執行一組工作來建立索引、使用文件來載入索引,以及執行查詢。 在不同的階段中,我們採用捷徑,以簡化程式碼,讓程式碼更容易閱讀及傳達概念。 現在您已熟悉基本概念,請嘗試在 Web 應用程式中呼叫 Azure AI 搜尋服務 API 的教學課程。