Rychlý start: Fulltextové vyhledávání pomocí sad SDK Azure

Naučte se používat klientskou knihovnu Azure.Search.Documents v sadě Azure SDK k vytváření, načítání a dotazování indexu vyhledávání pomocí ukázkových dat pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmus hodnocení BM25 pro vyhodnocování výsledků.

Tento rychlý start obsahuje kroky pro následující sady SDK:

Požadavky

  • Účet Azure s aktivním předplatným. Vytvoření účtu zdarma

  • Azure AI Search. Pokud službu nemáte, vytvořte ji. Pro účely tohoto rychlého startu můžete použít úroveň Free.

  • Klíč rozhraní API a koncový bod služby. Přihlaste se k webu Azure Portal a vyhledejte vyhledávací službu.

    V přehledu zkopírujte adresu URL a uložte ji do Poznámkový blok pro pozdější krok. Příkladem koncového bodu může být https://mydemo.search.windows.net.

    V části Klíče zkopírujte a uložte klíč správce pro úplná práva pro vytváření a odstraňování objektů. Existují dva zaměnitelné primární a sekundární klíče. Zvolte jednu z nich.

    Get an HTTP endpoint and access key

Vytvoření, načtení a dotazování indexu

Zvolte programovací jazyk pro další krok. Klientské knihovny Azure.Search.Documents jsou k dispozici v sadách Azure SDK pro .NET, Python, Javu a JavaScript.

Vytvořte konzolovou aplikaci pomocí klientské knihovny Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání. Případně si můžete zdrojový kód stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Nastavení prostředí

  1. Spusťte Visual Studio a vytvořte nový projekt pro konzolovou aplikaci.

  2. V nástrojích>NuGet Správce balíčků vyberte Spravovat balíčky NuGet pro řešení....

  3. Vyberte Procházet.

  4. Vyhledejte balíček Azure.Search.Documents a vyberte verzi 11.0 nebo novější.

  5. Výběrem možnosti Nainstalovat vpravo přidejte sestavení do projektu a řešení.

Vytvoření vyhledávacího klienta

  1. V Program.cs změňte obor názvů na AzureSearch.SDK.Quickstart.v11 a přidejte následující using direktivy.

    using Azure;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    using Azure.Search.Documents.Models;
    
  2. Vytvořte dva klienty: SearchIndexClient vytvoří index a SearchClient načte a dotazuje existující index. Oba potřebují koncový bod služby a klíč rozhraní API pro správu pro ověřování s právy k vytvoření nebo odstranění.

    Vzhledem k tomu, že kód sestaví identifikátor URI za vás, zadejte pouze název vyhledávací služby ve vlastnosti 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);
         . . . 
     }
    

Vytvoření indexu

V tomto rychlém startu vytvoříte index hotelů, na který načtete data hotelů a spustíte dotazy. V tomto kroku definujte pole v indexu. Každá definice pole obsahuje název, datový typ a atributy, které určují způsob použití pole.

V tomto příkladu se pro jednoduchost a čitelnost používají synchronní metody knihovny Azure.Search.Documents. V produkčních scénářích byste ale měli použít asynchronní metody, které umožňují udržovat aplikaci škálovatelnou a responzivní. Místo CreateIndex byste například použili CreateIndexAsync.

  1. Přidání prázdné definice třídy do projektu: Hotel.cs

  2. Zkopírujte následující kód do Hotel.cs a definujte strukturu hotelového dokumentu. Atributy v poli určují, jak se používá v aplikaci. Atribut musí být například IsFilterable přiřazen ke každému poli, které podporuje výraz filtru.

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

    V klientské knihovně Azure.Search.Documents můžete k zjednodušení definic polí použít SearchableField a SimpleField . Oba jsou deriváty vyhledávacího pole a můžou potenciálně zjednodušit váš kód:

    • SimpleField může být libovolný datový typ, je vždy nehledatelný (je ignorován pro dotazy fulltextového vyhledávání) a je načítaný (není skrytý). Ostatní atributy jsou ve výchozím nastavení vypnuté, ale je možné je povolit. Můžete použít SimpleField pro ID dokumentu nebo pole použitá pouze v filtrech, omezujících vlastností nebo v bodovacích profilech. Pokud ano, nezapomeňte použít všechny atributy, které jsou nezbytné pro daný scénář, například IsKey = true pro ID dokumentu. Další informace najdete v tématu SimpleFieldAttribute.cs ve zdrojovém kódu.

    • SearchableField musí být řetězec a je vždy prohledávatelný a načístelný. Ostatní atributy jsou ve výchozím nastavení vypnuté, ale je možné je povolit. Vzhledem k tomu, že tento typ pole je prohledávatelný, podporuje synonyma a úplný doplněk vlastností analyzátoru. Další informace najdete v SearchableFieldAttribute.cs ve zdrojovém kódu.

    Bez ohledu na to, jestli používáte základní SearchField rozhraní API nebo jeden z pomocných modelů, musíte explicitně povolit atributy filtru, omezující vlastnosti a řazení. Například IsFilterable, IsSortable a IsFacetable musí být explicitně přiřazeny, jak je znázorněno v ukázce výše.

  3. Přidejte do projektu druhou definici prázdné třídy: Address.cs. Zkopírujte do třídy následující kód.

    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. Vytvořte dvě další třídy: Hotel.Methods.cs a Address.Methods.cs pro přepsání ToString(). Tyto třídy slouží k vykreslení výsledků hledání ve výstupu konzoly. Obsah těchto tříd není v tomto článku k dispozici, ale kód můžete zkopírovat ze souborů na GitHubu.

  5. V Program.cs vytvořte SearchIndex objekt a potom volání CreateIndex metoda vyjádřit index ve vyhledávací službě. Index obsahuje také SearchSuggester , který povolí automatické dokončování v zadaných polích.

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

Nahrání dokumentů

Azure AI Search vyhledá obsah uložený ve službě. V tomto kroku načtete dokumenty JSON, které odpovídají právě vytvořenému indexu hotelu.

Ve službě Azure AI Search jsou vyhledávací dokumenty datové struktury, které jsou vstupy indexování a výstupy z dotazů. Jak je získáno z externího zdroje dat, vstupy dokumentů můžou být řádky v databázi, objekty blob v úložišti objektů blob nebo dokumenty JSON na disku. V tomto příkladu přebíráme zástupce a vkládáme dokumenty JSON pro čtyři hotely v samotném kódu.

Při nahrávání dokumentů musíte použít objekt IndexDocumentsBatch . Objekt IndexDocumentsBatch obsahuje kolekci akcí, z nichž každý obsahuje dokument a vlastnost, která službě Azure AI Search říká, jakou akci provést (nahrání, sloučení, odstranění a mergeOrUpload).

  1. V Program.cs vytvořte pole dokumentů a akcí indexu a pak předejte pole do IndexDocumentsBatch. Následující dokumenty odpovídají indexu rychlého startu hotelů, jak je definováno hotelovou třídou.

    // 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 = "Secret Point Motel",
                    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 = "Twin Dome Motel",
                    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 = "Triple 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 Cliff Hotel",
                    Description = "Sublime Cliff 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 Cliff is part of a lovingly restored 1800 palace.",
                    DescriptionFr = "Le sublime Cliff 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 Cliff 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}");
        }
    }
    

    Jakmile inicializujete IndexDocumentsBatch objekt, můžete jej odeslat do indexu voláním IndexDocuments na objekt SearchClient .

  2. Přidejte do main() následující řádky. Načítání dokumentů se provádí pomocí SearchClient, ale operace také vyžaduje oprávnění správce služby, která je obvykle přidružená k SearchIndexClient. Jedním ze způsobů, jak nastavit tuto operaci, je získat SearchClient prostřednictvím SearchIndexClient (v tomto příkladu adminClient).

     SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
    
     // Load documents
     Console.WriteLine("{0}", "Uploading documents...\n");
     UploadDocuments(ingesterClient);
    
  3. Vzhledem k tomu, že se jedná o konzolovou aplikaci, která spouští všechny příkazy postupně, přidejte 2sekundovou dobu čekání mezi indexováním a dotazy.

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

    Dvousekundové zpoždění kompenzuje indexování, což je asynchronní, aby se všechny dokumenty mohly indexovat před spuštěním dotazů. Kódování ve zpoždění je obvykle nezbytné pouze v ukázkách, testech a ukázkových aplikacích.

Prohledání indexu

Výsledky dotazu můžete získat hned po indexování prvního dokumentu, ale skutečné testování indexu by mělo počkat na indexování všech dokumentů.

Tato část přidává dvě funkce: logiku dotazu a výsledky. Pro dotazy použijte metodu Search . Tato metoda přebírá hledaný text (řetězec dotazu) a další možnosti.

SearchResults třída představuje výsledky.

  1. V Program.cs vytvořte metodu WriteDocuments , která vytiskne výsledky hledání do konzoly.

    // 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. Vytvořte metodu RunQueries pro spouštění dotazů a vracení výsledků. Výsledky jsou objekty Hotelu. Tato ukázka ukazuje podpis metody a první dotaz. Tento dotaz ukazuje parametr Select, který umožňuje vytvořit výsledek pomocí vybraných polí z dokumentu.

    // 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. Ve druhém dotazu vyhledejte termín, přidejte filtr, který vybere dokumenty, ve kterých je hodnocení větší než 4, a potom řadit podle hodnocení v sestupném pořadí. Filtr je logický výraz, který se vyhodnocuje přes pole IsFilterable v indexu. Dotazy filtrování zahrnují nebo vylučují hodnoty. Proto neexistuje žádné skóre relevance přidružené k dotazu filtru.

    // 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. Třetí dotaz ukazuje pole searchFields, která slouží k určení rozsahu operace fulltextového vyhledávání na konkrétní pole.

    // 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. Čtvrtý dotaz ukazuje omezující vlastnosti, které lze použít ke strukturování fasetové navigační struktury.

     // 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. V pátém dotazu vraťte konkrétní dokument. Vyhledání dokumentu je typická odpověď na událost OnClick v sadě výsledků.

     // 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. Poslední dotaz zobrazí syntaxi automatického dokončování, která simuluje částečný vstup uživatele sa, který se přeloží na dvě možné shody ve zdrojových polích přidružených k sugestivnímu modulu, který jste definovali v indexu.

     // Query 6
     Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
    
     var autoresponse = srchclient.Autocomplete("sa", "sg");
     WriteDocuments(autoresponse);
    
  8. Přidání RunQueries do 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();
    

Předchozí dotazy zobrazují v dotazu několik způsobů párování termínů: fulltextové vyhledávání, filtry a automatické dokončování.

Fulltextové vyhledávání a filtry se provádějí pomocí metody SearchClient.Search . Vyhledávací dotaz lze předat v řetězcisearchText, zatímco výraz filtru lze předat ve vlastnosti Filter třídy SearchOptions. Pokud chcete filtrovat bez hledání, stačí předat "*"searchText parametr metody Search . Pokud chcete hledat bez filtrování, nechejte Filter vlastnost nenasazenou nebo vůbec nepředávejte SearchOptions instanci.

Spuštění programu

Stisknutím klávesy F5 znovu sestavíte aplikaci a spustíte program v plném rozsahu.

Výstup obsahuje zprávy z Console.WriteLine s přidáním informací o dotazu a výsledků.

Vyčištění prostředků

Pokud pracujete s vlastním předplatným, je vhodné vždy na konci projektu zkontrolovat, jestli budete vytvořené prostředky ještě potřebovat. Prostředky, které necháte spuštěné, vás stojí peníze. Prostředky můžete odstraňovat jednotlivě nebo můžete odstranit skupinu prostředků, a odstranit tak celou sadu prostředků najednou.

Prostředky můžete najít a spravovat na portálu pomocí odkazu Všechny prostředky nebo skupiny prostředků v levém navigačním podokně.

Pokud používáte bezplatnou službu, mějte na paměti, že jste omezeni na tři indexy, indexery a zdroje dat. Jednotlivé položky na portálu můžete odstranit, abyste zůstali pod limitem.

Další kroky

V tomto rychlém startu jste prošli sadou úloh, kterými jste vytvořili index, načetli ho s dokumenty a spustili dotazy. V různých fázích jsme vzali zástupce, abychom zjednodušili kód pro čitelnost a porozumění. Teď, když znáte základní koncepty, vyzkoušejte kurz, který volá rozhraní API služby Azure AI Search ve webové aplikaci.