Share via


如何在 C# .NET 應用程式中使用 Azure.Search.Documents

本文說明如何使用 C# 和 Azure.Search.Documents (第 11 版) 用戶端程式庫,在適用於 .NET 的 Azure SDK 中建立和管理搜尋物件。

關於第 11 版

適用於 .NET 的 Azure SDK 包含 Azure SDK 小組的 Azure.Search.Documents 用戶端程式庫,其功能相當於先前的用戶端程式庫:Microsoft.Azure.Search。 第 11 版在 Azure 可程式性方面更為一致。 某些範例包括 AzureKeyCredential 金鑰驗證,以及 JSON 序列化的 System.Text.Json.Serialization

如同舊版,您可以使用此程式庫進行下列動作:

  • 建立和管理搜尋索引、資料來源、索引子、技能集和同義字對應
  • 載入和管理索引中的搜尋文件
  • 執行查詢,無需處理 HTTP 和 JSON 的詳細資料
  • 叫用和管理 AI 擴充 (技能集) 和輸出

程式庫會以單一 Azure.Search.Documents NuGet 套件的形式散發,其中包含用來以程式設計方式存取搜尋服務的所有 API。

用戶端程式庫會定義類別,例如 SearchIndexSearchFieldSearchDocument,以及定義作業,例如 SearchIndexClientSearchClient 類別上的 SearchIndexClient.CreateIndexSearchClient.Search。 這些類別可編成以下命名空間:

Azure.Search.Documents (第 11 版) 的目標是 2020-06-30 搜尋服務規格

用戶端程式庫不提供服務管理作業,例如建立和調整搜尋服務及管理 API 金鑰。 如果您需要從 .NET 應用程式管理搜尋資源,請在適用於 .NET 的 Azure SDK 中使用 Microsoft.Azure.Management.Search 程式庫。

升級至第 11 版

如果您之前使用舊版 .NET SDK,並想升級至目前正式推出的版本,請參閱升級至 Azure AI 搜尋 .NET SDK 第 11 版

SDK 需求

  • Visual Studio 2019 或更新版本。

  • 擁有 Azure AI Search 服務。 為了使用 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 金鑰來執行此應用程式:

Screenshot of the Console.WriteLine output from the sample program.

用戶端類型

用戶端程式庫會針對不同作業使用三種用戶端類型:SearchIndexClient 用於建立、更新或刪除索引、SearchClient 用於載入或查詢索引,而 SearchIndexerClient 則可使用索引子和技能集。 本文會聚焦於前兩個類型。

所有用戶端都必須至少具備服務名稱或端點,以及 API 金鑰。 這項資訊通常包含在設定檔中,類似於 appsettings.jsonDotNetHowTo 範例應用程式 檔案內容。 若要從組態檔讀取,請將 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 isn't found
        Console.WriteLine("The index doesn't exist. No deletion occurred.");

注意

本文中的範例程式碼會使用同步方法進行簡化,但在您自己的應用程式中應使用非同步方法,使程式碼保持可調整且反應快速。 例如,您可以在以上方法中使用 DeleteIndexAsync 來取代 DeleteIndex

建立索引

您可以使用 SearchIndexClient 來建立索引。

下列方法會用定義新索引結構描述的 SearchField 物件清單來建立新的 SearchIndex 物件。 每個欄位均有一個名稱、資料類型和一些屬性,以用於定義欄位的搜尋行為。

您可以在模型類別使用 FieldBuilder 以定義欄位。 FieldBuilder 類別會檢查指定 Hotel 模型類別的公用屬性 (property) 和屬性 (attribute),進而使用反映來建立索引的 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 物件以及其組成部分的詳細資訊,請參閱 SearchIndex 屬性清單,以及 REST API 參考

注意

如有需要,您永遠可以直接建立 Field 物件清單,而不是使用FieldBuilder。 例如,您可能不想使用模型類別,或您可能需要使用不想藉由新增屬性來修改的現有模型類別。

在 Main() 中呼叫 CreateIndex

Main 會呼叫上述方法以建立新的 "hotels" 索引:

Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, indexClient);

使用模型類別進行資料表示

DotNetHowTo 範例會針對 HotelAddressRoom 資料結構使用模型類別。 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(SearchResults<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> 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,表示此欄位不會顯示在搜尋結果中。

欄位類型 描述和使用方式
SearchField 基底類別,其中大部分屬性都設定為 null,除了必要屬性 Name,而 AnalyzerName 預設為標準 Lucene。
SimpleField 協助程式模型。 可以是任何資料類型、一律不可搜尋 (全文檢索搜尋查詢會將其忽略),以及可擷取 (不會隱藏)。 其他屬性預設為關閉,但可以啟用。 您可以針對僅用於篩選、Facet 或評分設定檔的文件識別碼或欄位使用 SimpleField。 若是如此,請務必套用案例所需的任何屬性,例如文件識別碼的 IsKey = true。 如需詳細資訊,請參閱原始程式碼中的 SimpleFieldAttribute.cs
SearchableField 協助程式模型。 必須是字串,而且一律可搜尋並可擷取。 其他屬性預設為關閉,但可以啟用。 因為此欄位類型是可搜尋,所以其支援同義字和分析器屬性的完整補語。 如需詳細資訊,請參閱原始程式碼中的 SearchableFieldAttribute.cs

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

新增欄位屬性

請注意每個欄位以屬性裝飾的方式,例如 IsFilterableIsSortableIsKeyAnalyzerName。 這些屬性會直接對應至 Azure AI 搜尋服務索引中的對應ˊ為屬性FieldBuilder 類別會使用這些屬性來建構索引的欄位定義。

欄位類型對應

屬性的 .NET 類型會對應至索引定義中相等的欄位類型。 例如,Category 字串屬性會對應至 category 欄位 (此欄位屬於 Edm.String 類型)。 bool?Edm.BooleanDateTimeOffset?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)
{
    IndexDocumentsBatch<Hotel> 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);

此方法分四個部分。 第一個部分會建立三個 Hotel 物件的陣列,個別包含三個 Room 物件做為我們上傳到索引的輸入資料。 為簡單起見,此資料採硬式編碼。 在實際應用程式中,資料可能會來自 SQL 資料庫之類的外部資料來源。

第二個部分會建立包含文件的 IndexDocumentsBatch 。 您在建立批次時 (在此案例中,是藉由呼叫 IndexDocumentsAction.Upload),指定要套用至該批次的作業。 接著以 IndexDocuments 方法將該 Batch 上傳至 Azure AI 搜尋服務索引。

注意

在此範例中,我們只上傳文件。 如果您想要將變更合併至現有的文件,或是刪除文件,您可以改為呼叫 IndexDocumentsAction.MergeIndexDocumentsAction.MergeOrUploadIndexDocumentsAction.Delete 來建立批次。 您也可以在單一批次中混合不同的作業,方法是呼叫 IndexBatch.New,它會採用一組 IndexDocumentsAction 物件,其中每個物件都會要求 Azure AI 搜尋服務針對文件執行特定的作業。 您可以建立每個擁有自己作業的 IndexDocumentsAction,方法是呼叫對應的方法,例如 IndexDocumentsAction.MergeIndexAction.Upload 等等。

此方法的第三部分是擷取區塊,該區塊會為編制索引處理重要錯誤情況。 如果您的搜尋服務無法將批次中的一些文件編制索引,系統會擲回 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);

執行查詢

首先,設定 SearchClient,用於讀取 appsettings.json 的服務端點和查詢 API 金鑰:

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 物件。 此物件用於指定查詢的其他選項,例如排序、篩選、分頁及 Facet。 在此方法中,我們會針對不同查詢設定 FilterSelectOrderBy 屬性。 如需搜尋查詢運算式語法的詳細資訊,請參閱簡單查詢語法

下一個步驟是查詢執行。 執行搜尋將會使用 SearchClient.Search 方法。 針對每次查詢,需要傳遞搜尋文字做為字串 (如果沒有搜尋文字,則傳遞 "*"),並再加上先前建立的搜尋選項。 我們也指定了 Hotel 做為 SearchClient.Search 的類型參數,藉此告訴 SDK 將搜尋結果中的文件還原序列化為 Hotel 類型的物件。

private static void RunQueries(SearchClient searchClient)
{
    SearchOptions options;
    SearchResults<Hotel> results;

    Console.WriteLine("Query 1: Search for 'motel'. Return only the HotelName in results:\n");

    options = new SearchOptions();
    options.Select.Add("HotelName");

    results = searchClient.Search<Hotel>("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.Search<Hotel>("*", 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.Search<Hotel>("*", 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" isn't supported yet when deserializing search result to "Hotel"
    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.Search<Hotel>("hotel", options);

    WriteDocuments(results);
}

第三,定義回應的寫入方法,將每份文件列印至主控台:

private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> 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.Search<Hotel>("motel", options);

WriteDocuments(results);

在此案例中,我們會在整個索引的所有可搜尋欄位中搜尋「motel」一字,而我們只想要擷取旅館名稱,如同選項 Select 所指定。 以下是結果:

Name: Secret Point Motel

Name: Twin Dome Motel

在第二個查詢中,使用篩選來選取每晚費用低於 $100 的房間。 結果中僅傳回旅館識別碼和描述:

options = new SearchOptions()
{
    Filter = "Rooms/any(r: r/BaseRate lt 100)"
};
options.Select.Add("HotelId");
options.Select.Add("Description");

results = searchClient.Search<Hotel>("*", options);

上述查詢會使用 OData $filter 運算式 (Rooms/any(r: r/BaseRate lt 100)),以篩選索引中的文件。 這會使用任何運算子,將 '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.Search<Hotel>("*", options);

WriteDocuments(results);

在最後一個查詢中,尋找符合「hotel」一字的所有旅館名稱:

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.Search<Hotel>("hotel", options);

WriteDocuments(results);

本節對 .NET SDK 的簡介到此結束,但還有其他內容等待您探索。 下一節會推薦其他資源,協助您深入瞭解如何使用 Azure AI 搜尋進行程式設計。

下一步