How to use Azure.Search.Documents in a C# .NET Application

W tym artykule wyjaśniono, jak tworzyć obiekty wyszukiwania i zarządzać nimi przy użyciu języka C# i biblioteki klienta Azure.Search.Documents (wersja 11) w zestawie Azure SDK dla platformy .NET.

Informacje o wersji 11

Zestaw Azure SDK dla platformy .NET zawiera bibliotekę klienta Azure.Search.Documents z zespołu zestawu Azure SDK, która jest funkcjonalnie równoważna poprzedniej bibliotece klienta Microsoft.Azure.Search. Wersja 11 jest bardziej spójna pod względem możliwości programowania na platformie Azure. Niektóre przykłady obejmują AzureKeyCredential uwierzytelnianie klucza i System.Text.Json.Serialization na potrzeby serializacji JSON.

Podobnie jak w przypadku poprzednich wersji, możesz użyć tej biblioteki do:

  • Tworzenie indeksów wyszukiwania, źródeł danych, indeksatorów, zestawów umiejętności i map synonimów i zarządzanie nimi
  • Ładowanie dokumentów wyszukiwania i zarządzanie nimi w indeksie
  • Wykonywanie zapytań bez konieczności obsługi szczegółów protokołu HTTP i JSON
  • Wywoływanie i zarządzanie wzbogacaniem sztucznej inteligencji (zestawami umiejętności) i danymi wyjściowymi

Biblioteka jest dystrybuowana jako pojedynczy pakiet NuGet Azure.Search.Documents, który zawiera wszystkie interfejsy API używane do programowego dostępu do usługi wyszukiwania.

Biblioteka kliencka definiuje klasy, takie jak SearchIndex, SearchFieldi SearchDocument, oraz operacje, takie jak SearchIndexClient.CreateIndex i SearchClient.Search w SearchIndexClient klasach i SearchClient . Te klasy są zorganizowane w następujące przestrzenie nazw:

Azure.Search.Documents (wersja 11) jest przeznaczona dla specyfikacji usługi wyszukiwania 2020-06-30.

Biblioteka klienta nie zapewnia operacji zarządzania usługami, takich jak tworzenie i skalowanie usług wyszukiwania oraz zarządzanie kluczami interfejsu API. Jeśli musisz zarządzać zasobami wyszukiwania z poziomu aplikacji .NET, użyj biblioteki Microsoft.Azure.Management.Search w zestawie Azure SDK dla platformy .NET.

Uaktualnianie do wersji 11

Jeśli używasz poprzedniej wersji zestawu .NET SDK i chcesz przeprowadzić uaktualnienie do bieżącej ogólnie dostępnej wersji, zobacz Uaktualnianie do zestawu .NET SDK usługi Azure AI Search w wersji 11.

Wymagania dotyczące zestawu SDK

Zestaw Azure SDK dla platformy .NET jest zgodny z platformą .NET Standard 2.0.

Przykładowa aplikacja

Ten artykuł "uczy według przykładu", korzystając z przykładu kodu DotNetHowTo w usłudze GitHub, aby zilustrować podstawowe pojęcia w usłudze Azure AI Search — w szczególności sposób tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania.

W pozostałej części tego artykułu przyjmij nowy indeks o nazwie "hotels" wypełniony kilkoma dokumentami z kilkoma zapytaniami zgodnymi z wynikami.

Poniżej znajduje się główny program przedstawiający ogólny przepływ:

// 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();
}

Następnie znajduje się częściowy zrzut ekranu danych wyjściowych, przy założeniu, że ta aplikacja jest uruchamiana z prawidłową nazwą usługi i kluczami interfejsu API:

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

Typy klientów

Biblioteka klienta używa trzech typów klientów dla różnych operacji: SearchIndexClient do tworzenia, aktualizowania lub usuwania indeksów, SearchClient ładowania lub wykonywania zapytań względem indeksu oraz SearchIndexerClient pracy z indeksatorami i zestawami umiejętności. Ten artykuł koncentruje się na dwóch pierwszych.

Co najmniej wszyscy klienci wymagają nazwy usługi lub punktu końcowego oraz klucza interfejsu API. Te informacje są często podane w pliku konfiguracji, podobnie jak w appsettings.json pliku przykładowej aplikacji DotNetHowTo. Aby odczytać plik konfiguracji, dodaj using Microsoft.Extensions.Configuration; go do programu.

Poniższa instrukcja tworzy klienta indeksu używanego do tworzenia, aktualizowania lub usuwania indeksów. Przyjmuje punkt końcowy usługi i klucz interfejsu API administratora.

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;
}

Następna instrukcja tworzy klienta wyszukiwania używanego do ładowania dokumentów lub uruchamiania zapytań. SearchClient wymaga indeksu. Do załadowania dokumentów potrzebny będzie klucz interfejsu API administratora, ale do uruchamiania zapytań można użyć klucza interfejsu API zapytań.

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;
}

Uwaga

Jeśli podasz nieprawidłowy klucz dla operacji importowania (na przykład klucz zapytania, w którym był wymagany klucz administratora), SearchClient zostanie wyświetlony CloudException komunikat o błędzie "Zabronione" przy pierwszym wywołaniu metody operacji. Jeśli tak się stanie, sprawdź dwukrotnie klucz interfejsu API.

Usuwanie indeksu

We wczesnych etapach programowania warto dołączyć instrukcję DeleteIndex , aby usunąć indeks pracy w toku, aby można było go odtworzyć przy użyciu zaktualizowanej definicji. Przykładowy kod usługi Azure AI Search często zawiera krok usuwania, aby można było ponownie uruchomić przykład.

Następujące wywołania DeleteIndexIfExistswiersza:

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

Ta metoda używa podanej SearchIndexClient metody, aby sprawdzić, czy indeks istnieje, a jeśli tak, usuwa go:

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.");

Uwaga

Przykładowy kod w tym artykule używa metod synchronicznych dla uproszczenia, ale należy użyć metod asynchronicznych we własnych aplikacjach, aby zapewnić ich skalowalność i elastyczność. Na przykład w powyższej metodzie można użyć DeleteIndexAsync zamiast DeleteIndex.

Tworzenie indeksu

Możesz użyć SearchIndexClient polecenia , aby utworzyć indeks.

Poniższa metoda tworzy nowy SearchIndex obiekt z listą SearchField obiektów definiujących schemat nowego indeksu. Każde pole ma nazwę, typ danych i kilka atrybutów, które definiują jego zachowanie wyszukiwania.

Pola można zdefiniować na podstawie klasy modelu przy użyciu polecenia FieldBuilder. Klasa FieldBuilder używa odbicia, aby utworzyć listę SearchField obiektów dla indeksu, sprawdzając właściwości publiczne i atrybuty danej Hotel klasy modelu. Przyjrzymy się bliżej Hotel klasie później.

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);
}

Oprócz pól można również dodać profile oceniania, sugestory lub opcje CORS do indeksu (te parametry zostaną pominięte w przykładzie w celu zwięzłości). Więcej informacji na temat obiektu SearchIndex i jego części SearchIndex składowych można znaleźć na liście właściwości, a także w dokumentacji interfejsu API REST.

Uwaga

Zawsze można utworzyć listę Field obiektów bezpośrednio, zamiast używać ich FieldBuilder w razie potrzeby. Na przykład możesz nie chcieć użyć klasy modelu lub użyć istniejącej klasy modelu, której nie chcesz modyfikować, dodając atrybuty.

Wywołaj metodę CreateIndex w pliku Main()

Main Tworzy nowy indeks "hotels" przez wywołanie powyższej metody:

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

Używanie klasy modelu na potrzeby reprezentacji danych

Przykład DotNetHowTo używa klas modelu dla struktur danych Hotel, Address i Room . HotelAddressodwołuje się do typu złożonego pojedynczego poziomu (pola wieloczęściowego) i Room (kolekcji pól wieloczęściowych).

Za pomocą tych typów można utworzyć i załadować indeks oraz utworzyć strukturę odpowiedzi z zapytania:

// 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();
}

Alternatywną metodą jest bezpośrednie dodawanie pól do indeksu. Poniższy przykład przedstawia tylko kilka pól.

 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 }
         }
 };

Definicje pola

Model danych na platformie .NET i odpowiadający mu schemat indeksu powinien obsługiwać środowisko wyszukiwania, które chcesz przekazać użytkownikowi końcowemu. Każdy obiekt najwyższego poziomu na platformie .NET, taki jak dokument wyszukiwania w indeksie wyszukiwania, odpowiada wynikowi wyszukiwania przedstawionemu w interfejsie użytkownika. Na przykład w aplikacji wyszukiwania hotelowego użytkownicy końcowi mogą chcieć wyszukiwać według nazwy hotelu, funkcji hotelu lub cech określonego pokoju.

W każdej klasie pole jest definiowane za pomocą typu danych i atrybutów określających sposób jego użycia. Nazwa każdej właściwości publicznej w każdej klasie jest mapowania na pole o tej samej nazwie w definicji indeksu.

Zapoznaj się z poniższym fragmentem kodu, który ściąga kilka definicji pól z klasy Hotel. Zwróć uwagę, że adresy i pokoje są typami języka C# z własnymi definicjami klas (zapoznaj się z przykładowym kodem, jeśli chcesz je wyświetlić). Oba są typami złożonymi. Aby uzyskać więcej informacji, zobacz How to model complex types (Jak modelować złożone typy).

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; }

Wybieranie klasy pól

Podczas definiowania pól można użyć klasy bazowej SearchField lub użyć modeli pomocników pochodnych, które służą jako "szablony", ze wstępnie skonfigurowanymi właściwościami.

Dokładnie jedno pole w indeksie musi służyć jako klucz dokumentu (IsKey = true). Musi być ciągiem i musi jednoznacznie identyfikować każdy dokument. Wymagane jest również posiadanie IsHidden = trueelementu , co oznacza, że nie może być widoczne w wynikach wyszukiwania.

Typ pola Opis i użycie
SearchField Klasa bazowa, z większością właściwości ustawionych na wartość null, z wyjątkiem Name wymaganej wartości domyślnej dla AnalyzerName standardowej Lucene.
SimpleField Model pomocnika. Może być dowolnym typem danych, zawsze nie można wyszukiwać (jest ignorowany w przypadku zapytań wyszukiwania pełnotekstowego) i jest pobierany (nie jest ukryty). Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Można użyć SimpleField elementu dla identyfikatorów dokumentów lub pól używanych tylko w filtrach, aspektach lub profilach oceniania. Jeśli tak, pamiętaj, aby zastosować wszelkie atrybuty niezbędne do scenariusza, takie jak IsKey = true identyfikator dokumentu. Aby uzyskać więcej informacji, zobacz SimpleFieldAttribute.cs w kodzie źródłowym.
SearchableField Model pomocnika. Musi być ciągiem i zawsze można wyszukiwać i pobierać. Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Ponieważ ten typ pola można wyszukiwać, obsługuje synonimy i pełne uzupełnienie właściwości analizatora. Aby uzyskać więcej informacji, zobacz SearchableFieldAttribute.cs w kodzie źródłowym.

Niezależnie od tego, czy używasz podstawowego SearchField interfejsu API, czy jednego z modeli pomocnika, musisz jawnie włączyć atrybuty filtru, aspektu i sortowania. Na przykład IsFilterable, IsSortable i IsFacetable muszą być jawnie przypisane, jak pokazano w powyższym przykładzie.

Dodawanie atrybutów pola

Zwróć uwagę, że każde pole jest ozdobione atrybutami, takimi jak IsFilterable, IsSortable, IsKeyi AnalyzerName. Te atrybuty są mapowanie bezpośrednio na odpowiednie atrybuty pól w indeksie usługi Azure AI Search. Klasa FieldBuilder używa tych właściwości do konstruowania definicji pól dla indeksu.

Mapowanie typu pola

Typy właściwości platformy .NET mapują na ich równoważne typy pól w definicji indeksu. Na przykład właściwość ciągu Category jest mapowana na pole category mające typ Edm.String. Istnieją podobne mapowania typów między bool?, , Edm.BooleanDateTimeOffset?i Edm.DateTimeOffset itd.

Czy zdarzyło ci się zauważyć SmokingAllowed właściwość?

[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;

Atrybut JsonIgnore w tej właściwości informuje właściwość , FieldBuilder aby nie serializować jej do indeksu jako pola. Jest to doskonały sposób tworzenia właściwości obliczeniowych po stronie klienta, których można użyć jako pomocników w aplikacji. W tym przypadku właściwość odzwierciedla, SmokingAllowed czy obiekt Room w Rooms kolekcji zezwala na palenie. Jeśli wszystkie są fałszywe, oznacza to, że cały hotel nie zezwala na palenie.

Ładowanie indeksu

Następny krok w pliku Main wypełnia nowo utworzony indeks "hotels". Ta populacja indeksu jest wykonywana w następującej metodzie: (Kod został zastąpiony ciągiem "..." do celów ilustracyjnych. Zobacz pełne przykładowe rozwiązanie dla pełnego kodu populacji danych).

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);

Ta metoda ma cztery części. Pierwszy tworzy tablicę trzech obiektów z trzema HotelRoom obiektami, które będą służyć jako dane wejściowe do przekazania do indeksu. Te dane są zakodowane na twardo dla uproszczenia. W rzeczywistej aplikacji dane prawdopodobnie pochodzą z zewnętrznego źródła danych, takiego jak baza danych SQL.

Druga część tworzy IndexDocumentsBatch plik zawierający dokumenty. Należy określić operację, którą chcesz zastosować do partii w momencie jej utworzenia, w tym przypadku przez wywołanie metody IndexDocumentsAction.Upload. Następnie partia zostanie przekazana do indeksu usługi Azure AI Search za pomocą IndexDocuments metody .

Uwaga

W tym przykładzie po prostu przekazujemy dokumenty. Jeśli chcesz scalić zmiany z istniejącymi dokumentami lub usunąć dokumenty, możesz utworzyć partie, wywołując IndexDocumentsAction.Mergemetodę , IndexDocumentsAction.MergeOrUploadlub IndexDocumentsAction.Delete zamiast tego. Możesz również mieszać różne operacje w jednej partii, wywołując metodę IndexBatch.New, która pobiera kolekcję IndexDocumentsAction obiektów, z których każda informuje usługę Azure AI Search o wykonaniu określonej operacji na dokumencie. Każdy z nich można utworzyć IndexDocumentsAction przy użyciu własnej operacji, wywołując odpowiednią metodę, taką jak IndexDocumentsAction.Merge, IndexAction.Uploadi tak dalej.

Trzecią częścią tej metody jest blok catch, który obsługuje ważny przypadek błędu indeksowania. Jeśli usługa wyszukiwania nie może indeksować niektórych dokumentów w partii, zostanie zgłoszony element RequestFailedException . Wyjątek może wystąpić, jeśli indeksujesz dokumenty, gdy usługa jest obciążona dużym obciążeniem. Zdecydowanie zalecamy jawną obsługę tego przypadku w kodzie. Możesz opóźnić, a następnie ponowić indeksowanie dokumentów, których przetwarzanie zakończyło się niepowodzeniem, lub możesz zarejestrować błąd i kontynuować, tak jak w prezentowanym przykładzie. Możesz też wykonać inną akcję w zależności od wymagań spójności danych aplikacji. Alternatywą jest użycie elementu SearchIndexingBufferedSender do inteligentnego przetwarzania wsadowego, automatycznego opróżniania i ponawiania prób dla nieudanych akcji indeksowania. Zobacz ten przykład , aby uzyskać więcej kontekstu.

UploadDocuments Na koniec metoda opóźnia się przez dwie sekundy. Indeksowanie odbywa się asynchronicznie w usłudze wyszukiwania, więc przykładowa aplikacja musi poczekać chwilę, aby upewnić się, że dokumenty są dostępne do wyszukiwania. Tego typu opóźnienia są zazwyczaj konieczne tylko w przypadku pokazów, testów i przykładowych aplikacji.

Wywołaj metodę UploadDocuments w pliku Main()

Poniższy fragment kodu konfiguruje wystąpienie SearchClient metody GetSearchClient indexClient. Element indexClient używa klucza interfejsu API administratora w żądaniach, które są wymagane do ładowania lub odświeżania dokumentów.

Alternatywnym podejściem jest bezpośrednie wywołanie SearchClient klucza interfejsu API administratora w systemie AzureKeyCredential.

SearchClient searchClient = indexClient.GetSearchClient(indexName);

Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(searchClient);

Uruchamianie zapytań

Najpierw skonfiguruj element SearchClient odczytujący punkt końcowy usługi i klucz interfejsu API zapytań z appsettings.json:

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;
}

Po drugie zdefiniuj metodę, która wysyła żądanie zapytania.

Za każdym razem, gdy metoda wykonuje zapytanie, tworzy nowy SearchOptions obiekt. Ten obiekt służy do określania dodatkowych opcji zapytania, takich jak sortowanie, filtrowanie, stronicowanie i tworzenie aspektów. W tej metodzie ustawiamy Filterwłaściwość , Selecti OrderBy dla różnych zapytań. Aby uzyskać więcej informacji na temat składni wyrażenia zapytania wyszukiwania, prosta składnia zapytania.

Następnym krokiem jest wykonanie zapytania. Uruchomienie wyszukiwania odbywa się przy użyciu SearchClient.Search metody . Dla każdego zapytania przekaż tekst wyszukiwania do użycia jako ciąg (lub "*" jeśli nie ma tekstu wyszukiwania) oraz utworzone wcześniej opcje wyszukiwania. Określamy Hotel również jako parametr typu dla SearchClient.Searchparametru , który nakazuje zestawowi SDK deserializowanie dokumentów w wynikach wyszukiwania do obiektów typu 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);
}

Po trzecie zdefiniuj metodę zapisującą odpowiedź, drukującą każdy dokument w konsoli:

private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> result in searchResults.GetResults())
    {
        Console.WriteLine(result.Document);
    }

    Console.WriteLine();
}

Wywoływanie zapytań RunQueries w trybie Main()

SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);

Console.WriteLine("{0}", "Running queries...\n");
RunQueries(indexClientForQueries);

Eksplorowanie konstrukcji zapytań

Przyjrzyjmy się bliżej każdemu z zapytań. Oto kod do wykonania pierwszego zapytania:

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

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

WriteDocuments(results);

W tym przypadku przeszukujemy cały indeks słowa "motel" w dowolnym polu z możliwością wyszukiwania i chcemy pobrać nazwy hoteli zgodnie z opcją Select . Oto wyniki:

Name: Secret Point Motel

Name: Twin Dome Motel

W drugim zapytaniu użyj filtru, aby wybrać pokoje z nocną stawką mniejszą niż 100 USD. Zwróć tylko identyfikator hotelu i opis w wynikach:

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

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

Powyższe zapytanie używa wyrażenia OData $filter , Rooms/any(r: r/BaseRate lt 100)do filtrowania dokumentów w indeksie. Używa to dowolnego operatora, aby zastosować element "BaseRate lt 100" do każdego elementu w kolekcji Rooms. Aby uzyskać więcej informacji, zobacz Składnia filtru OData.

W trzecim zapytaniu znajdź dwa najlepsze hotele, które zostały ostatnio odnowione, i pokaż nazwę hotelu i datę ostatniej renowacji. Oto kod:

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);

W ostatnim zapytaniu znajdź wszystkie nazwy hoteli, które pasują do słowa "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);

Ta sekcja zawiera podsumowanie tego wprowadzenia do zestawu .NET SDK, ale nie zatrzymaj się tutaj. W następnej sekcji przedstawiono inne zasoby, aby dowiedzieć się więcej na temat programowania za pomocą usługi Azure AI Search.

Następne kroki