Sdílet prostřednictvím


Rychlý start: Fulltextové vyhledávání

V tomto rychlém startu použijete klientskou knihovnu Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání s ukázkovými daty pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Požadavky pro Microsoft Entra ID

Pro doporučené ověřování bez klíčů s ID Microsoft Entra musíte:

  • Nainstalujte Azure CLI.

  • Přiřaďte role uživatelskému účtu Search Service Contributor a Search Index Data Contributor. Role můžete přiřadit na webu Azure Portal v části Řízení přístupu (IAM)>Přidat přiřazení role. Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Načtení informací o prostředcích

Abyste mohli aplikaci ověřit pomocí Search Azure AI, musíte načíst následující informace:

Název proměnné Hodnota
SEARCH_API_ENDPOINT Tuto hodnotu najdete na webu Azure Portal. Vyberte vyhledávací službu a pak v nabídce vlevo vyberte Přehled. Hodnota url v části Essentials je koncový bod, který potřebujete. Příkladem koncového bodu může být https://mydemo.search.windows.net.

Přečtěte si další informace o ověřování bez klíčů a nastavení proměnných prostředí.

Nastavení

  1. Vytvořte novou složku full-text-quickstart , která bude obsahovat aplikaci, a otevřete v této složce Visual Studio Code pomocí následujícího příkazu:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Vytvořte novou konzolovou aplikaci pomocí následujícího příkazu:

    dotnet new console
    
  3. Nainstalujte klientskou knihovnu Azure AI Search (Azure.Search.Documents) pro .NET pomocí:

    dotnet add package Azure.Search.Documents
    
  4. Pro doporučené ověřování bez klíčů s ID Microsoft Entra nainstalujte balíček Azure.Identity pomocí:

    dotnet add package Azure.Identity
    
  5. Pro doporučené ověřování bez klíčů pomocí ID Microsoft Entra se přihlaste k Azure pomocí následujícího příkazu:

    az login
    

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

V předchozí části nastavení jste vytvořili novou konzolovou aplikaci a nainstalovali klientskou knihovnu Azure AI Search.

V této části přidáte kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spuštěním programu zobrazíte výsledky v konzole. Podrobné vysvětlení kódu najdete v části s vysvětlením kódu .

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
  1. Do Program.cs vložte následující kód. serviceName Upravte proměnné apiKey pomocí názvu vyhledávací služby a klíče rozhraní API správce.

    using System;
    using Azure;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    using Azure.Search.Documents.Models;
    
    namespace AzureSearch.Quickstart
    
    {
        class Program
        {
            static void Main(string[] args)
            {    
                // Your search service endpoint
                Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
    
                // Use the recommended keyless credential instead of the AzureKeyCredential credential.
                DefaultAzureCredential credential = new();
                //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
    
                // Create a SearchIndexClient to send create/delete index commands
                SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential);
    
                // Create a SearchClient to load and query documents
                string indexName = "hotels-quickstart";
                SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential);
    
                // Delete index if it exists
                Console.WriteLine("{0}", "Deleting index...\n");
                DeleteIndexIfExists(indexName, searchIndexClient);
    
                // Create index
                Console.WriteLine("{0}", "Creating index...\n");
                CreateIndex(indexName, searchIndexClient);
    
                SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);
    
                // Load documents
                Console.WriteLine("{0}", "Uploading documents...\n");
                UploadDocuments(ingesterClient);
    
                // Wait 2 secondsfor indexing to complete before starting queries (for demo and console-app purposes only)
                Console.WriteLine("Waiting for indexing...\n");
                System.Threading.Thread.Sleep(2000);
    
                // Call the RunQueries method to invoke a series of queries
                Console.WriteLine("Starting queries...\n");
                RunQueries(searchClient);
    
                // End the program
                Console.WriteLine("{0}", "Complete. Press any key to end this program...\n");
                Console.ReadKey();
            }
    
            // Delete the hotels-quickstart index to reuse its name
            private static void DeleteIndexIfExists(string indexName, SearchIndexClient searchIndexClient)
            {
                searchIndexClient.GetIndexNames();
                {
                    searchIndexClient.DeleteIndex(indexName);
                }
            }
            // Create hotels-quickstart index
            private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient)
            {
                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);
    
                searchIndexClient.CreateOrUpdateIndex(definition);
            }
    
            // 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 = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
                            Category = "Boutique",
                            Tags = new[] { "view", "air conditioning", "concierge" },
                            ParkingIncluded = false,
                            LastRenovationDate = new DateTimeOffset(2022, 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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                            Category = "Boutique",
                            Tags = new[] { "pool", "free wifi", "concierge" },
                            ParkingIncluded = false,
                            LastRenovationDate = new DateTimeOffset(2019, 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 Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                            Category = "Suite",
                            Tags = new[] { "restaurant", "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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                            Category = "Boutique",
                            Tags = new[] { "concierge", "view", "air conditioning" },
                            ParkingIncluded = true,
                            LastRenovationDate = new DateTimeOffset(2020, 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}");
                }
            }
    
            // Run queries, use WriteDocuments to print output
            private static void RunQueries(SearchClient searchClient)
            {
                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("Rating");
    
                response = searchClient.Search<Hotel>("*", options);
                WriteDocuments(response);
    
                // 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 = searchClient.Search<Hotel>("hotels", options);
                WriteDocuments(response);
    
                // 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 = searchClient.Search<Hotel>("pool", options);
                WriteDocuments(response);
    
                // Query 4 - Use Facets to return a faceted navigation structure for a given query
                // Filters are typically used with facets to narrow results on OnClick events
                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 = searchClient.Search<Hotel>("*", options);
                WriteDocuments(response);
    
                // Query 5
                Console.WriteLine("Query #5: Look up a specific document...\n");
    
                Response<Hotel> lookupResponse;
                lookupResponse = searchClient.GetDocument<Hotel>("3");
    
                Console.WriteLine(lookupResponse.Value.HotelId);
    
    
                // Query 6
                Console.WriteLine("Query #6: Call Autocomplete on HotelName...\n");
    
                var autoresponse = searchClient.Autocomplete("sa", "sg");
                WriteDocuments(autoresponse);
    
            }
    
            // 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. Ve stejné složce vytvořte nový soubor s názvem Hotel.cs a vložte následující kód. Tento kód definuje strukturu hotelového dokumentu.

    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(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; }
        }
    }
    
  3. Vytvořte nový soubor s názvem Hotel.cs a vložte následující kód, který definuje 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(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; }
        }
    }
    
  4. Vytvořte nový soubor s názvem Address.cs a vložte následující kód, který definuje strukturu dokumentu adresy.

    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; }
        }
    }
    
  5. Vytvořte nový soubor s názvem Hotel.Methods.cs a vložte následující kód, který definuje přepsání ToString() pro Hotel třídu.

    using System;
    using System.Text;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            public override string ToString()
            {
                var builder = new StringBuilder();
    
                if (!String.IsNullOrEmpty(HotelId))
                {
                    builder.AppendFormat("HotelId: {0}\n", HotelId);
                }
    
                if (!String.IsNullOrEmpty(HotelName))
                {
                    builder.AppendFormat("Name: {0}\n", HotelName);
                }
    
                if (!String.IsNullOrEmpty(Description))
                {
                    builder.AppendFormat("Description: {0}\n", Description);
                }
    
                if (!String.IsNullOrEmpty(Category))
                {
                    builder.AppendFormat("Category: {0}\n", Category);
                }
    
                if (Tags != null && Tags.Length > 0)
                {
                    builder.AppendFormat("Tags: [ {0} ]\n", String.Join(", ", Tags));
                }
    
                if (ParkingIncluded.HasValue)
                {
                    builder.AppendFormat("Parking included: {0}\n", ParkingIncluded.Value ? "yes" : "no");
                }
    
                if (LastRenovationDate.HasValue)
                {
                    builder.AppendFormat("Last renovated on: {0}\n", LastRenovationDate);
                }
    
                if (Rating.HasValue)
                {
                    builder.AppendFormat("Rating: {0}\n", Rating);
                }
    
                if (Address != null && !Address.IsEmpty)
                {
                    builder.AppendFormat("Address: \n{0}\n", Address.ToString());
                }
    
                return builder.ToString();
            }
        }
    }
    
  6. Vytvořte nový soubor s názvem Address.Methods.cs a vložte následující kód, který definuje přepsání ToString() pro Address třídu.

    using System;
    using System.Text;
    using System.Text.Json.Serialization;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Address
        {
            public override string ToString()
            {
                var builder = new StringBuilder();
    
                if (!IsEmpty)
                {
                    builder.AppendFormat("{0}\n{1}, {2} {3}\n{4}", StreetAddress, City, StateProvince, PostalCode, Country);
                }
    
                return builder.ToString();
            }
    
            [JsonIgnore]
            public bool IsEmpty => String.IsNullOrEmpty(StreetAddress) &&
                                   String.IsNullOrEmpty(City) &&
                                   String.IsNullOrEmpty(StateProvince) &&
                                   String.IsNullOrEmpty(PostalCode) &&
                                   String.IsNullOrEmpty(Country);
        }
    }
    
  7. Sestavte a spusťte aplikaci pomocí následujícího příkazu:

    dotnet run
    

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

Vysvětlení kódu

V předchozích částech jste vytvořili novou konzolovou aplikaci a nainstalovali klientskou knihovnu Azure AI Search. Přidali jste kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spustili jste program, abyste zobrazili výsledky v konzole.

V této části vysvětlujeme kód, který jste přidali do konzolové aplikace.

Vytvoření vyhledávacího klienta

V Program.cs jste vytvořili dva klienty:

Oba klienti potřebují koncový bod vyhledávací služby a přihlašovací údaje popsané výše v části s informacemi o prostředcích.

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
static void Main(string[] args)
{
    // Your search service endpoint
    Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");

    // Use the recommended keyless credential instead of the AzureKeyCredential credential.
    DefaultAzureCredential credential = new();
    //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");

    // Create a SearchIndexClient to send create/delete index commands
    SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential);

    // Create a SearchClient to load and query documents
    string indexName = "hotels-quickstart";
    SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential);
    
    // REDACTED FOR BREVITY . . . 
}

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 definujete 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.

Definování struktur

Vytvořili jste dvě pomocné třídy, Hotel.cs a Address.cs, abyste definovali strukturu hotelového dokumentu a jeho adresy. Třída Hotel obsahuje pole pro ID hotelu, název, popis, kategorii, značky, parkování, datum renovace, hodnocení a adresu. Třída Address obsahuje pole pro adresu ulice, město, stát/kraj, PSČ a zemi/oblast.

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ý (ignorován pro dotazy fulltextového vyhledávání) a je možné je načíst (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 předchozí ukázce.

Vytvoření indexu vyhledávání

V Program.cs vytvoříte SearchIndex objekt a pak zavoláte 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 searchIndexClient)
{
    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);

    searchIndexClient.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í indexu hotelu, který jste vytvořili.

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

V Program.cs vytvoříte pole dokumentů a akcí indexu a pak předáte pole do IndexDocumentsBatch. Následující dokumenty odpovídají indexu pro rychlý start 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 = "Stay-Kay City Hotel",
                Description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
                Category = "Boutique",
                Tags = new[] { "view", "air conditioning", "concierge" },
                ParkingIncluded = false,
                LastRenovationDate = new DateTimeOffset(2022, 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"
                }
            }),
        // REDACTED FOR BREVITY
}

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

Dokumenty načítáte pomocí SearchClient in Main(), ale operace také vyžaduje oprávnění správce služby, která je obvykle přidružena k SearchIndexClient. Jedním zezpůsobůch SearchIndexClientsearchIndexClient

SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);

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

Vzhledem k tomu, že máme konzolovou aplikaci, která spouští všechny příkazy postupně, přidáme 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.

V Program.csWriteDocuments metoda 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();
}

Příklad dotazu 1

Metoda RunQueries provádí dotazy a vrací výsledky. Výsledky jsou objekty Hotelu. Tato ukázka ukazuje podpis metody a první dotaz. Tento dotaz ukazuje Select parametr, 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 searchClient)
{
    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 = searchClient.Search<Hotel>("*", options);
    WriteDocuments(response);
    // REDACTED FOR BREVITY
}

Příklad dotazu 2

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 = searchClient.Search<Hotel>("hotels", options);
WriteDocuments(response);

Příklad dotazu 3

Třetí dotaz ukazuje 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 = searchClient.Search<Hotel>("pool", options);
WriteDocuments(response);

Příklad dotazu 4

Čtvrtý dotaz ukazuje facets, 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 = searchClient.Search<Hotel>("*", options);
WriteDocuments(response);

Příklad dotazu 5

V pátém dotazu vraťte konkrétní dokument. Vyhledání dokumentu je typická odpověď na OnClick událost v sadě výsledků.

// Query 5
Console.WriteLine("Query #5: Look up a specific document...\n");

Response<Hotel> lookupResponse;
lookupResponse = searchClient.GetDocument<Hotel>("3");

Console.WriteLine(lookupResponse.Value.HotelId);

Příklad dotazu 6

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 = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);

Souhrn dotazů

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.

V tomto rychlém startu použijete klientskou knihovnu Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání s ukázkovými daty pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Požadavky pro Microsoft Entra ID

Pro doporučené ověřování bez klíčů s ID Microsoft Entra musíte:

  • Nainstalujte Azure CLI.

  • Přiřaďte role Search Service Contributor a Search Index Data Contributor k vašemu uživatelskému účtu. Role můžete přiřadit na webu Azure Portal v části Řízení přístupu (IAM)>Přidat přiřazení role. Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Načtení informací o prostředcích

Abyste mohli aplikaci ověřit pomocí Search Azure AI, musíte načíst následující informace:

Název proměnné Hodnota
SEARCH_API_ENDPOINT Tuto hodnotu najdete na webu Azure Portal. Vyberte vyhledávací službu a pak v nabídce vlevo vyberte Přehled. Hodnota url v části Essentials je koncový bod, který potřebujete. Příkladem koncového bodu může být https://mydemo.search.windows.net.

Přečtěte si další informace o ověřování bez klíčů a nastavení proměnných prostředí.

Nastavení

Ukázka v tomto rychlém startu funguje s modulem Runtime Java. Nainstalujte sadu Java Development Kit, jako je Azul Zulu OpenJDK. Měl by fungovat také microsoft build OpenJDK nebo upřednostňovaná sada JDK.

  1. Nainstalujte Apache Maven. Pak spusťte a potvrďte mvn -v úspěšnou instalaci.

  2. V kořenovém adresáři projektu vytvořte nový pom.xml soubor a zkopírujte do něj následující kód:

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>azure.search.sample</groupId>
        <artifactId>azuresearchquickstart</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <build>
            <sourceDirectory>src</sourceDirectory>
            <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                <source>1.8</source>
                <target>1.8</target>
                </configuration>
            </plugin>
            </plugins>
        </build>
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-search-documents</artifactId>
                <version>11.7.3</version>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-core</artifactId>
                <version>1.53.0</version>
            </dependency>
            <dependency>
                <groupId>com.azure</groupId>
                <artifactId>azure-identity</artifactId>
                <version>1.15.1</version>
            </dependency>
        </dependencies>
    </project>
    
  3. Nainstalujte závislosti včetně klientské knihovny Azure AI Search (Azure.Search.Documents) pro klientskou knihovnu Java a Azure Identity pro Javu pomocí:

    mvn clean dependency:copy-dependencies
    
  4. Pro doporučené ověřování bez klíčů pomocí ID Microsoft Entra se přihlaste k Azure pomocí následujícího příkazu:

    az login
    

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

V předchozí části nastavení jste nainstalovali klientskou knihovnu Azure AI Search a další závislosti.

V této části přidáte kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spuštěním programu zobrazíte výsledky v konzole. Podrobné vysvětlení kódu najdete v části s vysvětlením kódu .

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Vytvořte nový soubor s názvem App.java a vložte do App.java následující kód:

    import java.util.Arrays;
    import java.util.ArrayList;
    import java.time.OffsetDateTime;
    import java.time.ZoneOffset;
    import java.time.LocalDateTime;
    import java.time.LocalDate;
    import java.time.LocalTime;
    import com.azure.core.util.Configuration;
    import com.azure.core.util.Context;
    import com.azure.identity.DefaultAzureCredential;
    import com.azure.identity.DefaultAzureCredentialBuilder;
    import com.azure.search.documents.SearchClient;
    import com.azure.search.documents.SearchClientBuilder;
    import com.azure.search.documents.indexes.SearchIndexClient;
    import com.azure.search.documents.indexes.SearchIndexClientBuilder;
    import com.azure.search.documents.indexes.models.IndexDocumentsBatch;
    import com.azure.search.documents.models.SearchOptions;
    import com.azure.search.documents.indexes.models.SearchIndex;
    import com.azure.search.documents.indexes.models.SearchSuggester;
    import com.azure.search.documents.util.AutocompletePagedIterable;
    import com.azure.search.documents.util.SearchPagedIterable;
    
    public class App {
    
        public static void main(String[] args) {
            // Your search service endpoint
            "https://<Put your search service NAME here>.search.windows.net/";
    
            // Use the recommended keyless credential instead of the AzureKeyCredential credential.
            DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
            //AzureKeyCredential credential = new AzureKeyCredential("<Your search service admin key>");
    
            // Create a SearchIndexClient to send create/delete index commands
            SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
                .endpoint(searchServiceEndpoint)
                .credential(credential)
                .buildClient();
    
            // Create a SearchClient to load and query documents
            String indexName = "hotels-quickstart-java";
            SearchClient searchClient = new SearchClientBuilder()
                .endpoint(searchServiceEndpoint)
                .credential(credential)
                .indexName(indexName)
                .buildClient();
    
            // Create Search Index for Hotel model
            searchIndexClient.createOrUpdateIndex(
                new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
                .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
    
            // Upload sample hotel documents to the Search Index
            uploadDocuments(searchClient);
    
            // Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
            System.out.println("Waiting for indexing...\n");
            try
            {
                Thread.sleep(2000);
            }
            catch (InterruptedException e)
            {
            }
    
            // Call the RunQueries method to invoke a series of queries
            System.out.println("Starting queries...\n");
            RunQueries(searchClient);
    
            // End the program
            System.out.println("Complete.\n");
        }
    
        // Upload documents in a single Upload request.
        private static void uploadDocuments(SearchClient searchClient)
        {
            var hotelList = new ArrayList<Hotel>();
    
            var hotel = new Hotel();
            hotel.hotelId = "1";
            hotel.hotelName = "Stay-Kay City Hotel";
            hotel.description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "view", "air conditioning", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2022, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 3.6;
            hotel.address = new Address();
            hotel.address.streetAddress = "677 5th Ave";
            hotel.address.city = "New York";
            hotel.address.stateProvince = "NY";
            hotel.address.postalCode = "10022";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "2";
            hotel.hotelName = "Old Century Hotel";
            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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
            hotel.category = "Boutique";
            hotel.tags = new String[] { "pool", "free wifi", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2019, 2, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 3.60;
            hotel.address = new Address();
            hotel.address.streetAddress = "140 University Town Center Dr";
            hotel.address.city = "Sarasota";
            hotel.address.stateProvince = "FL";
            hotel.address.postalCode = "34243";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "3";
            hotel.hotelName = "Gastronomic Landscape Hotel";
            hotel.description = "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.";
            hotel.category = "Suite";
            hotel.tags = new String[] { "restaurant", "bar", "continental breakfast" };
            hotel.parkingIncluded = true;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2015, 9, 20), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 4.80;
            hotel.address = new Address();
            hotel.address.streetAddress = "3393 Peachtree Rd";
            hotel.address.city = "Atlanta";
            hotel.address.stateProvince = "GA";
            hotel.address.postalCode = "30326";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "4";
            hotel.hotelName = "Sublime Palace Hotel";
            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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "concierge", "view", "air conditioning" };
            hotel.parkingIncluded = true;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2020, 2, 06), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 4.60;
            hotel.address = new Address();
            hotel.address.streetAddress = "7400 San Pedro Ave";
            hotel.address.city = "San Antonio";
            hotel.address.stateProvince = "TX";
            hotel.address.postalCode = "78216";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            var batch = new IndexDocumentsBatch<Hotel>();
            batch.addMergeOrUploadActions(hotelList);
            try
            {
                searchClient.indexDocuments(batch);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                // If for some reason any documents are dropped during indexing, you can compensate by delaying and
                // retrying. This simple demo just logs failure and continues
                System.err.println("Failed to index some of the documents");
            }
        }
    
        // Write search results to console
        private static void WriteSearchResults(SearchPagedIterable searchResults)
        {
            searchResults.iterator().forEachRemaining(result ->
            {
                Hotel hotel = result.getDocument(Hotel.class);
                System.out.println(hotel);
            });
    
            System.out.println();
        }
    
        // Write autocomplete results to console
        private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
        {
            autocompleteResults.iterator().forEachRemaining(result ->
            {
                String text = result.getText();
                System.out.println(text);
            });
    
            System.out.println();
        }
    
        // Run queries, use WriteDocuments to print output
        private static void RunQueries(SearchClient searchClient)
        {
            // Query 1
            System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
    
            SearchOptions options = new SearchOptions();
            options.setIncludeTotalCount(true);
            options.setFilter("");
            options.setOrderBy("");
            options.setSelect("HotelId", "HotelName", "Address/City");
    
            WriteSearchResults(searchClient.search("*", options, Context.NONE));
    
            // Query 2
            System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
    
            options = new SearchOptions();
            options.setFilter("Rating gt 4");
            options.setOrderBy("Rating desc");
            options.setSelect("HotelId", "HotelName", "Rating");
    
            WriteSearchResults(searchClient.search("hotels", options, Context.NONE));
    
            // Query 3
            System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");
    
            options = new SearchOptions();
            options.setSearchFields("Tags");
    
            options.setSelect("HotelId", "HotelName", "Tags");
    
            WriteSearchResults(searchClient.search("pool", options, Context.NONE));
    
            // Query 4
            System.out.println("Query #4: Facet on 'Category'...\n");
    
            options = new SearchOptions();
            options.setFilter("");
            options.setFacets("Category");
            options.setSelect("HotelId", "HotelName", "Category");
    
            WriteSearchResults(searchClient.search("*", options, Context.NONE));
    
            // Query 5
            System.out.println("Query #5: Look up a specific document...\n");
    
            Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
            System.out.println(lookupResponse.hotelId);
            System.out.println();
    
             // Query 6
            System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
    
            WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
        }
    }
    
  2. Vytvořte nový soubor s názvem Hotel.java a vložte do Hotel.java následující kód:

    import com.azure.search.documents.indexes.SearchableField;
    import com.azure.search.documents.indexes.SimpleField;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.annotation.JsonInclude.Include;
    
    import java.time.OffsetDateTime;
    
    /**
     * Model class representing a hotel.
     */
    @JsonInclude(Include.NON_NULL)
    public class Hotel {
        /**
         * Hotel ID
         */
        @JsonProperty("HotelId")
        @SimpleField(isKey = true)
        public String hotelId;
    
        /**
         * Hotel name
         */
        @JsonProperty("HotelName")
        @SearchableField(isSortable = true)
        public String hotelName;
    
        /**
         * Description
         */
        @JsonProperty("Description")
        @SearchableField(analyzerName = "en.microsoft")
        public String description;
    
        /**
         * Category
         */
        @JsonProperty("Category")
        @SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
        public String category;
    
        /**
         * Tags
         */
        @JsonProperty("Tags")
        @SearchableField(isFilterable = true, isFacetable = true)
        public String[] tags;
    
        /**
         * Whether parking is included
         */
        @JsonProperty("ParkingIncluded")
        @SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
        public Boolean parkingIncluded;
    
        /**
         * Last renovation time
         */
        @JsonProperty("LastRenovationDate")
        @SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
        public OffsetDateTime lastRenovationDate;
    
        /**
         * Rating
         */
        @JsonProperty("Rating")
        @SimpleField(isFilterable = true, isSortable = true, isFacetable = true)
        public Double rating;
    
        /**
         * Address
         */
        @JsonProperty("Address")
        public Address address;
    
        @Override
        public String toString()
        {
            try
            {
                return new ObjectMapper().writeValueAsString(this);
            }
            catch (JsonProcessingException e)
            {
                e.printStackTrace();
                return "";
            }
        }
    }
    
  3. Vytvořte nový soubor s názvem Address.java a vložte do Address.java následující kód:

    import com.azure.search.documents.indexes.SearchableField;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.annotation.JsonInclude.Include;
    
    /**
     * Model class representing an address.
     */
    @JsonInclude(Include.NON_NULL)
    public class Address {
        /**
         * Street address
         */
        @JsonProperty("StreetAddress")
        @SearchableField
        public String streetAddress;
    
        /**
         * City
         */
        @JsonProperty("City")
        @SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
        public String city;
    
        /**
         * State or province
         */
        @JsonProperty("StateProvince")
        @SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
        public String stateProvince;
    
        /**
         * Postal code
         */
        @JsonProperty("PostalCode")
        @SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
        public String postalCode;
    
        /**
         * Country
         */
        @JsonProperty("Country")
        @SearchableField(isFilterable = true, isSortable = true, isFacetable = true)
        public String country;
    }
    
  4. Spusťte novou konzolovou aplikaci:

    javac Address.java App.java Hotel.java -cp ".;target\dependency\*"
    java -cp ".;target\dependency\*" App
    

Vysvětlení kódu

V předchozích částech jste vytvořili novou konzolovou aplikaci a nainstalovali klientskou knihovnu Azure AI Search. Přidali jste kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spustili jste program, abyste zobrazili výsledky v konzole.

V této části vysvětlujeme kód, který jste přidali do konzolové aplikace.

Vytvoření vyhledávacího klienta

V App.java jste vytvořili dva klienty:

  • SearchIndexClient vytvoří index.
  • SearchClient načte a dotazuje existující index.

Oba klienti potřebují koncový bod vyhledávací služby a přihlašovací údaje popsané výše v části s informacemi o prostředcích.

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
public static void main(String[] args) {
    // Your search service endpoint
    String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";

    // Use the recommended keyless credential instead of the AzureKeyCredential credential.
    DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
    //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");

    // Create a SearchIndexClient to send create/delete index commands
    SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
        .endpoint(searchServiceEndpoint)
        .credential(credential)
        .buildClient();
    
    // Create a SearchClient to load and query documents
    String indexName = "hotels-quickstart-java";
    SearchClient searchClient = new SearchClientBuilder()
        .endpoint(searchServiceEndpoint)
        .credential(credential)
        .indexName(indexName)
        .buildClient();

    // Create Search Index for Hotel model
    searchIndexClient.createOrUpdateIndex(
        new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
        .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));

    // REDACTED FOR BREVITY . . . 
}

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 definujete 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.

Definování struktur

Vytvořili jste dvě pomocné třídy, Hotel.java a Address.java, abyste definovali strukturu hotelového dokumentu a jeho adresy. Třída hotelu obsahuje pole pro ID hotelu, název, popis, kategorii, značky, parkování, datum renovace, hodnocení a adresu. Třída Adresa obsahuje pole pro adresu ulice, město, stát/kraj, PSČ a zemi/oblast.

V klientské knihovně Azure.Search.Documents můžete k zjednodušení definic polí použít SearchableField a SimpleField .

  • SimpleField může být libovolný datový typ, je vždy nehledatelný (ignorován pro dotazy fulltextového vyhledávání) a je možné je načíst (není skrytý). Ostatní atributy jsou ve výchozím nastavení vypnuté, ale je možné je povolit. Pro ID dokumentu nebo pole použitá pouze v filtrech, fazetách nebo v bodovacích profilech můžete použít SimpleField. Pokud ano, nezapomeňte použít všechny atributy, které jsou nezbytné pro scénář, například IsKey = true pro ID dokumentu.
  • 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.

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, isSortablea isFacetable musí být explicitně atribut, jak je znázorněno v předchozí ukázce.

Vytvoření indexu vyhledávání

V App.javaaplikaci vytvoříte SearchIndex objekt v main metodě a potom zavoláte metodu createOrUpdateIndex pro vytvoření indexu ve vyhledávací službě. Index obsahuje SearchSuggester také povolení automatického dokončování u zadaných polí.

// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
    new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
    .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));

Nahrání dokumentů

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

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 IndexActions, 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).

V App.javaaplikaci vytvoříte dokumenty a akce indexu a pak je IndexDocumentsBatchpředáte . Následující dokumenty odpovídají indexu pro rychlý start hotelů, jak je definováno hotelovou třídou.

private static void uploadDocuments(SearchClient searchClient)
{
    var hotelList = new ArrayList<Hotel>();

    var hotel = new Hotel();
    hotel.hotelId = "1";
    hotel.hotelName = "Stay-Kay City Hotel";
    hotel.description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
    hotel.category = "Boutique";
    hotel.tags = new String[] { "view", "air conditioning", "concierge" };
    hotel.parkingIncluded = false;
    hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2022, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
    hotel.rating = 3.6;
    hotel.address = new Address();
    hotel.address.streetAddress = "677 5th Ave";
    hotel.address.city = "New York";
    hotel.address.stateProvince = "NY";
    hotel.address.postalCode = "10022";
    hotel.address.country = "USA";
    hotelList.add(hotel);
    
    // REDACTED FOR BREVITY

    var batch = new IndexDocumentsBatch<Hotel>();
    batch.addMergeOrUploadActions(hotelList);
    try
    {
        searchClient.indexDocuments(batch);
    }
    catch (Exception e)
    {
        e.printStackTrace();
        // If for some reason any documents are dropped during indexing, you can compensate by delaying and
        // retrying. This simple demo just logs failure and continues
        System.err.println("Failed to index some of the documents");
    }
}

Jakmile objekt inicializujete IndexDocumentsBatch , můžete ho odeslat do indexu voláním indexDocuments ve vašem SearchClient objektu.

Dokumenty načítáte pomocí SearchClient in main(), ale operace také vyžaduje oprávnění správce služby, která je obvykle přidružena k SearchIndexClient. Jedním zezpůsobůch SearchIndexClientsearchIndexClient

uploadDocuments(searchClient);

Vzhledem k tomu, že máme konzolovou aplikaci, která spouští všechny příkazy postupně, přidáme 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)
System.out.println("Waiting for indexing...\n");
try
{
    Thread.sleep(2000);
}
catch (InterruptedException e)
{
}

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á dvě části funkčnosti: 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.

Metoda App.javavypíše WriteDocuments výsledky hledání do konzoly.

// Write search results to console
private static void WriteSearchResults(SearchPagedIterable searchResults)
{
    searchResults.iterator().forEachRemaining(result ->
    {
        Hotel hotel = result.getDocument(Hotel.class);
        System.out.println(hotel);
    });

    System.out.println();
}

// Write autocomplete results to console
private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
{
    autocompleteResults.iterator().forEachRemaining(result ->
    {
        String text = result.getText();
        System.out.println(text);
    });

    System.out.println();
}

Příklad dotazu 1

Metoda RunQueries provádí dotazy a vrací výsledky. Výsledky jsou objekty Hotelu. Tato ukázka ukazuje podpis metody a první dotaz. Tento dotaz ukazuje Select parametr, 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 searchClient)
{
    // Query 1
    System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");

    SearchOptions options = new SearchOptions();
    options.setIncludeTotalCount(true);
    options.setFilter("");
    options.setOrderBy("");
    options.setSelect("HotelId", "HotelName", "Address/City");

    WriteSearchResults(searchClient.search("*", options, Context.NONE));
}

Příklad dotazu 2

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 isFilterable pole v indexu. Dotazy filtrování zahrnují nebo vylučují hodnoty. Proto neexistuje žádné skóre relevance přidružené k dotazu filtru.

// Query 2
System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");

options = new SearchOptions();
options.setFilter("Rating gt 4");
options.setOrderBy("Rating desc");
options.setSelect("HotelId", "HotelName", "Rating");

WriteSearchResults(searchClient.search("hotels", options, Context.NONE));

Příklad dotazu 3

Třetí dotaz ukazuje searchFields, který slouží k určení rozsahu operace fulltextového vyhledávání na konkrétní pole.

// Query 3
System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");

options = new SearchOptions();
options.setSearchFields("Tags");

options.setSelect("HotelId", "HotelName", "Tags");

WriteSearchResults(searchClient.search("pool", options, Context.NONE));

Příklad dotazu 4

Čtvrtý dotaz ukazuje facets, který lze použít ke strukturování fasetové navigační struktury.

// Query 4
System.out.println("Query #4: Facet on 'Category'...\n");

options = new SearchOptions();
options.setFilter("");
options.setFacets("Category");
options.setSelect("HotelId", "HotelName", "Category");

WriteSearchResults(searchClient.search("*", options, Context.NONE));

Příklad dotazu 5

V pátém dotazu vraťte konkrétní dokument.

// Query 5
System.out.println("Query #5: Look up a specific document...\n");

Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
System.out.println(lookupResponse.hotelId);
System.out.println();

Příklad dotazu 6

Poslední dotaz ukazuje syntaxi automatického dokončování, která simuluje částečný uživatelský vstup s , který se přeloží na dvě možné shody v sourceFields přidruženém s návrhu, který jste definovali v indexu.

// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");

WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));

Souhrn dotazů

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 searchText řetězci, zatímco výraz filtru lze předat ve filter vlastnosti SearchOptions třídy. Pokud chcete filtrovat bez hledání, stačí předat searchText parametr search metody "*". Pokud chcete hledat bez filtrování, nechejte filter vlastnost nenasazenou nebo vůbec nepředávejte SearchOptions instanci.

V tomto rychlém startu použijete klientskou knihovnu Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání s ukázkovými daty pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Požadavky pro Microsoft Entra ID

Pro doporučené ověřování bez klíčů s ID Microsoft Entra musíte:

  • Nainstalujte Azure CLI.

  • Přiřaďte role Search Service Contributor a Search Index Data Contributor vašemu uživatelskému účtu. Role můžete přiřadit na webu Azure Portal v části Řízení přístupu (IAM)>Přidat přiřazení role. Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Načtení informací o prostředcích

Abyste mohli aplikaci ověřit pomocí Search Azure AI, musíte načíst následující informace:

Název proměnné Hodnota
SEARCH_API_ENDPOINT Tuto hodnotu najdete na webu Azure Portal. Vyberte vyhledávací službu a pak v nabídce vlevo vyberte Přehled. Hodnota url v části Essentials je koncový bod, který potřebujete. Příkladem koncového bodu může být https://mydemo.search.windows.net.

Přečtěte si další informace o ověřování bez klíčů a nastavení proměnných prostředí.

Nastavení

  1. Vytvořte novou složku full-text-quickstart , která bude obsahovat aplikaci, a otevřete v této složce Visual Studio Code pomocí následujícího příkazu:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Vytvořte následující package.json příkaz:

    npm init -y
    
  3. Nainstalujte klientskou knihovnu Azure AI Search (Azure.Search.Documents) pro JavaScript pomocí:

    npm install @azure/search-documents
    
  4. Pro doporučené ověřování bez hesla nainstalujte klientskou knihovnu Azure Identity pomocí:

    npm install @azure/identity
    

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

V předchozí části nastavení jste nainstalovali klientskou knihovnu Azure AI Search a další závislosti.

V této části přidáte kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spuštěním programu zobrazíte výsledky v konzole. Podrobné vysvětlení kódu najdete v části s vysvětlením kódu .

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Vytvořte nový soubor s názvem index.js a vložte do index.js následující kód:

    // Import from the @azure/search-documents library
    import { SearchIndexClient, odata } from "@azure/search-documents";
    // Import from the Azure Identity library
    import { DefaultAzureCredential } from "@azure/identity";
    // Importing the hotels sample data
    import hotelData from './hotels.json' assert { type: "json" };
    // Load the .env file if it exists
    import * as dotenv from "dotenv";
    dotenv.config();
    // Defining the index definition
    const indexDefinition = {
        "name": "hotels-quickstart",
        "fields": [
            {
                "name": "HotelId",
                "type": "Edm.String",
                "key": true,
                "filterable": true
            },
            {
                "name": "HotelName",
                "type": "Edm.String",
                "searchable": true,
                "filterable": false,
                "sortable": true,
                "facetable": false
            },
            {
                "name": "Description",
                "type": "Edm.String",
                "searchable": true,
                "filterable": false,
                "sortable": false,
                "facetable": false,
                "analyzerName": "en.lucene"
            },
            {
                "name": "Description_fr",
                "type": "Edm.String",
                "searchable": true,
                "filterable": false,
                "sortable": false,
                "facetable": false,
                "analyzerName": "fr.lucene"
            },
            {
                "name": "Category",
                "type": "Edm.String",
                "searchable": true,
                "filterable": true,
                "sortable": true,
                "facetable": true
            },
            {
                "name": "Tags",
                "type": "Collection(Edm.String)",
                "searchable": true,
                "filterable": true,
                "sortable": false,
                "facetable": true
            },
            {
                "name": "ParkingIncluded",
                "type": "Edm.Boolean",
                "filterable": true,
                "sortable": true,
                "facetable": true
            },
            {
                "name": "LastRenovationDate",
                "type": "Edm.DateTimeOffset",
                "filterable": true,
                "sortable": true,
                "facetable": true
            },
            {
                "name": "Rating",
                "type": "Edm.Double",
                "filterable": true,
                "sortable": true,
                "facetable": true
            },
            {
                "name": "Address",
                "type": "Edm.ComplexType",
                "fields": [
                    {
                        "name": "StreetAddress",
                        "type": "Edm.String",
                        "filterable": false,
                        "sortable": false,
                        "facetable": false,
                        "searchable": true
                    },
                    {
                        "name": "City",
                        "type": "Edm.String",
                        "searchable": true,
                        "filterable": true,
                        "sortable": true,
                        "facetable": true
                    },
                    {
                        "name": "StateProvince",
                        "type": "Edm.String",
                        "searchable": true,
                        "filterable": true,
                        "sortable": true,
                        "facetable": true
                    },
                    {
                        "name": "PostalCode",
                        "type": "Edm.String",
                        "searchable": true,
                        "filterable": true,
                        "sortable": true,
                        "facetable": true
                    },
                    {
                        "name": "Country",
                        "type": "Edm.String",
                        "searchable": true,
                        "filterable": true,
                        "sortable": true,
                        "facetable": true
                    }
                ]
            }
        ],
        "suggesters": [
            {
                "name": "sg",
                "searchMode": "analyzingInfixMatching",
                "sourceFields": [
                    "HotelName"
                ]
            }
        ]
    };
    async function main() {
        // Your search service endpoint
        const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
        // Use the recommended keyless credential instead of the AzureKeyCredential credential.
        const credential = new DefaultAzureCredential();
        //const credential = new AzureKeyCredential(Your search service admin key);
        // Create a SearchIndexClient to send create/delete index commands
        const searchIndexClient = new SearchIndexClient(searchServiceEndpoint, credential);
        // Creating a search client to upload documents and issue queries
        const indexName = "hotels-quickstart";
        const searchClient = searchIndexClient.getSearchClient(indexName);
        console.log('Checking if index exists...');
        await deleteIndexIfExists(searchIndexClient, indexName);
        console.log('Creating index...');
        let index = await searchIndexClient.createIndex(indexDefinition);
        console.log(`Index named ${index.name} has been created.`);
        console.log('Uploading documents...');
        let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
        console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `);
        // waiting one second for indexing to complete (for demo purposes only)
        sleep(1000);
        console.log('Querying the index...');
        console.log();
        await sendQueries(searchClient);
    }
    async function deleteIndexIfExists(searchIndexClient, indexName) {
        try {
            await searchIndexClient.deleteIndex(indexName);
            console.log('Deleting index...');
        }
        catch {
            console.log('Index does not exist yet.');
        }
    }
    async function sendQueries(searchClient) {
        // Query 1
        console.log('Query #1 - search everything:');
        let searchOptions = {
            includeTotalCount: true,
            select: ["HotelId", "HotelName", "Rating"]
        };
        let searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log(`Result count: ${searchResults.count}`);
        console.log();
        // Query 2
        console.log('Query #2 - search with filter, orderBy, and select:');
        let state = 'FL';
        searchOptions = {
            filter: odata `Address/StateProvince eq ${state}`,
            orderBy: ["Rating desc"],
            select: ["HotelId", "HotelName", "Rating"]
        };
        searchResults = await searchClient.search("wifi", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
        // Query 3
        console.log('Query #3 - limit searchFields:');
        searchOptions = {
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
        searchResults = await searchClient.search("sublime palace", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
        // Query 4
        console.log('Query #4 - limit searchFields and use facets:');
        searchOptions = {
            facets: ["Category"],
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
        searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
        // Query 5
        console.log('Query #5 - Lookup document:');
        let documentResult = await searchClient.getDocument('3');
        console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);
        console.log();
    }
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    main().catch((err) => {
        console.error("The sample encountered an error:", err);
    });
    
  2. Vytvořte soubor s názvem hotels.json a vložte do hotels.json následující kód:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Stay-Kay City Hotel",
                "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
                "Category": "Boutique",
                "Tags": ["view", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "2022-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "2019-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Gastronomic Landscape Hotel",
                "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Category": "Suite",
                "Tags": ["restaurant", "bar", "continental breakfast"],
                "ParkingIncluded": "true",
                "LastRenovationDate": "2015-09-20T00:00:00Z",
                "Rating": 4.8,
                "Address": {
                    "StreetAddress": "3393 Peachtree Rd",
                    "City": "Atlanta",
                    "StateProvince": "GA",
                    "PostalCode": "30326"
                }
            },
            {
                "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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "air conditioning"],
                "ParkingIncluded": true,
                "LastRenovationDate": "2020-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. Vytvořte soubor s názvem hotels_quickstart_index.json a vložte do hotels_quickstart_index.json následující kód:

    {
    	"name": "hotels-quickstart",
    	"fields": [
    		{
    			"name": "HotelId",
    			"type": "Edm.String",
    			"key": true,
    			"filterable": true
    		},
    		{
    			"name": "HotelName",
    			"type": "Edm.String",
    			"searchable": true,
    			"filterable": false,
    			"sortable": true,
    			"facetable": false
    		},
    		{
    			"name": "Description",
    			"type": "Edm.String",
    			"searchable": true,
    			"filterable": false,
    			"sortable": false,
    			"facetable": false,
    			"analyzerName": "en.lucene"
    		},
    		{
    			"name": "Category",
    			"type": "Edm.String",
    			"searchable": true,
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Tags",
    			"type": "Collection(Edm.String)",
    			"searchable": true,
    			"filterable": true,
    			"sortable": false,
    			"facetable": true
    		},
    		{
    			"name": "ParkingIncluded",
    			"type": "Edm.Boolean",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "LastRenovationDate",
    			"type": "Edm.DateTimeOffset",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Rating",
    			"type": "Edm.Double",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Address",
    			"type": "Edm.ComplexType",
    			"fields": [
    				{
    					"name": "StreetAddress",
    					"type": "Edm.String",
    					"filterable": false,
    					"sortable": false,
    					"facetable": false,
    					"searchable": true
    				},
    				{
    					"name": "City",
    					"type": "Edm.String",
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "StateProvince",
    					"type": "Edm.String",
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "PostalCode",
    					"type": "Edm.String",
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "Country",
    					"type": "Edm.String",
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				}
    			]
    		}
    	],
    	"suggesters": [
    		{
    			"name": "sg",
    			"searchMode": "analyzingInfixMatching",
    			"sourceFields": [
    				"HotelName"
    			]
    		}
    	]
    }
    
  4. Přihlaste se k Azure pomocí následujícího příkazu:

    az login
    
  5. Spusťte kód JavaScriptu pomocí následujícího příkazu:

    node index.js
    

Vysvětlení kódu

Vytvoření indexu

Soubor hotels_quickstart_index.json definuje, jak Azure AI Search funguje s dokumenty, které načtete v dalším kroku. Každé pole je identifikováno a name má zadané type. Každé pole má také řadu atributů indexu, které určují, jestli může Azure AI Search prohledávat, filtrovat, řadit a omezující vlastnosti pole. Většina polí je jednoduchých datových typů, ale některé, jako AddressType jsou složité typy, které umožňují vytvářet bohaté datové struktury v indexu. Další informace opodporovaných

S naší definicí indexu chceme importovat hotels_quickstart_index.json v horní části index.js , aby hlavní funkce přistupovala k definici indexu.

const indexDefinition = require('./hotels_quickstart_index.json');

V rámci hlavní funkce pak vytvoříme , SearchIndexClientkterá se použije k vytváření a správě indexů pro Azure AI Search.

const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));

Dále chceme odstranit index, pokud už existuje. Tato operace je běžným postupem pro testovací nebo ukázkový kód.

Provedeme to tak, že definujeme jednoduchou funkci, která se pokusí odstranit index.

async function deleteIndexIfExists(indexClient, indexName) {
    try {
        await indexClient.deleteIndex(indexName);
        console.log('Deleting index...');
    } catch {
        console.log('Index does not exist yet.');
    }
}

Ke spuštění funkce extrahujeme název indexu z definice indexu indexNameindexClient a předáme deleteIndexIfExists() funkci spolu s funkcí.

const indexName = indexDefinition["name"];

console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);

Potom jsme připraveni vytvořit index pomocí createIndex() metody.

console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);

console.log(`Index named ${index.name} has been created.`);

Nahrání dokumentů

Ve službě Azure AI Search jsou dokumenty datové struktury, které jsou vstupy indexování a výstupy z dotazů. Tato data můžete odeslat do indexu nebo použít indexer. V tomto případě nahrajeme dokumenty do indexu prostřednictvím kódu programu.

Vstupy dokumentů můžou být řádky v databázi, objekty blob v úložišti objektů blob nebo jako v této ukázce dokumenty JSON na disku. Podobně jako v případě, že jsme to udělali indexDefinition, musíme také importovat hotels.json v horní části index.js , aby k datům bylo možné přistupovat v naší hlavní funkci.

const hotelData = require('./hotels.json');

Abychom mohli data indexovat do vyhledávacího indexu, musíme teď vytvořit .SearchClient SearchIndexClient Zatímco se používá k vytvoření a správě indexu, SearchClient slouží k nahrání dokumentů a dotazování indexu.

Existují dva způsoby, jak vytvořit SearchClient. První možností je vytvořit úplně SearchClient od začátku:

 const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));

Alternativně můžete použít getSearchClient() metodu SearchIndexClient vytvoření SearchClient:

const searchClient = indexClient.getSearchClient(indexName);

Teď, když je klient definovaný, nahrajte dokumenty do indexu vyhledávání. V tomto případě použijeme metodu mergeOrUploadDocuments() , která nahraje dokumenty nebo je sloučí s existujícím dokumentem, pokud už existuje dokument se stejným klíčem.

console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);

console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);

Prohledání indexu

Když jste vytvořili index a nahráli jste dokumenty, můžete do indexu odesílat dotazy. V této části pošleme do indexu vyhledávání pět různých dotazů, abychom vám ukázali různé části funkcí dotazů, které jsou vám k dispozici.

Dotazy jsou napsané ve sendQueries() funkci, kterou voláme v hlavní funkci následujícím způsobem:

await sendQueries(searchClient);

Dotazy se odesílají pomocí search() metody searchClient. Prvním parametrem je hledaný text a druhý parametr určuje možnosti hledání.

Příklad dotazu 1

První dotaz vyhledá *, což je ekvivalent pro hledání všeho a vybere tři pole v indexu. Osvědčeným postupem je pouze select pole, která potřebujete, protože stažení nepotřebných dat může do dotazů přidat latenci.

Pro searchOptions tento dotaz je includeTotalCount také nastavena truehodnota , která vrátí počet nalezených odpovídajících výsledků.

async function sendQueries(searchClient) {
    console.log('Query #1 - search everything:');
    let searchOptions = {
        includeTotalCount: true,
        select: ["HotelId", "HotelName", "Rating"]
    };

    let searchResults = await searchClient.search("*", searchOptions);
    for await (const result of searchResults.results) {
        console.log(`${JSON.stringify(result.document)}`);
    }
    console.log(`Result count: ${searchResults.count}`);

    // remaining queries go here
}

Zbývající níže uvedené dotazy by se také měly přidat do sendQueries() funkce. Jsou zde odděleny pro čitelnost.

Příklad dotazu 2

V dalším dotazu určíme hledaný termín "wifi" a zahrneme také filtr, který vrátí pouze výsledky, ve kterých je stav roven 'FL'. Výsledky jsou také objednány hotelovým hotelem Rating.

console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
    filter: odata`Address/StateProvince eq ${state}`,
    orderBy: ["Rating desc"],
    select: ["HotelId", "HotelName", "Rating"]
};

searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Příklad dotazu 3

Dále je hledání omezeno na jedno prohledávatelné pole pomocí parametru searchFields . Tento přístup je skvělou možností, jak zefektivnit dotaz, pokud víte, že vás zajímají jenom shody v určitých polích.

console.log('Query #3 - Limit searchFields:');
searchOptions = {
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("Sublime Palace", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}
console.log();

Příklad dotazu 4

Další běžnou možností zahrnutí do dotazu je facets. Omezující vlastnosti umožňují vytvářet filtry v uživatelském rozhraní, aby uživatelé snadno věděli, na jaké hodnoty můžou filtrovat.

console.log('Query #4 - Use facets:');
searchOptions = {
    facets: ["Category"],
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Příklad dotazu 5

Poslední dotaz používá getDocument() metodu searchClient. Díky tomu můžete dokument efektivně načíst podle jeho klíče.

console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)

Souhrn dotazů

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í searchClient.search metody. Vyhledávací dotaz lze předat v řetězci searchText , zatímco výraz filtru lze předat ve filter vlastnosti SearchOptions třídy. Pokud chcete filtrovat bez hledání, stačí předat searchText parametr search metody "*". Pokud chcete hledat bez filtrování, nechejte filter vlastnost nenasazenou nebo vůbec nepředávejte SearchOptions instanci.

V tomto rychlém startu použijete PowerShell a rozhraní REST API služby Azure AI Search k vytvoření, načtení a dotazování indexu vyhledávání pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Konfigurace přístupu

Ke službě Azure AI Search se můžete připojit pomocí klíčů rozhraní API nebo ID Microsoft Entra s přiřazeními rolí. Klíče se snadněji spouštějí, ale role jsou bezpečnější.

Konfigurace doporučeného přístupu na základě role:

  1. Přihlaste se do Azure portálu a vyberte svou vyhledávací službu.

  2. V levém podokně vyberte Nastavení>Klíče.

  3. V části Řízení přístupu k rozhraní API vyberte Obě.

    Tato možnost umožňuje ověřování založené na klíčích i bez klíčů. Po přiřazení rolí se můžete vrátit k tomuto kroku a vybrat řízení přístupu na základě role.

  4. V levém podokně vyberte Řízení přístupu (IAM).

  5. Vyberte Přidat>Přiřadit roli.

  6. Přiřaďte roli Přispěvatel vyhledávací služby a Přispěvatel dat indexu vyhledávání k vašemu uživatelskému účtu.

Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Získání koncového bodu

V další části zadáte následující koncový bod pro navázání připojení ke službě Azure AI Search. Tento postup předpokládá, že jste nakonfigurovali přístup na základě role.

Získání koncového bodu služby:

  1. Přihlaste se do Azure portálu a vyberte svou vyhledávací službu.

  2. V levém podokně vyberte Přehled.

  3. Poznamenejte si adresu URL, která by měla být podobná https://my-service.search.windows.net.

Než budete moct volat rozhraní REST API do služby Azure AI Search, musíte se k této službě ověřit a připojit. V PowerShellu provedete následující kroky, které podporují příkazy Azure CLI použité ve dvou a třech krocích.

Připojení k vyhledávací službě:

  1. V místním systému otevřete PowerShell.

  2. Přihlaste se ke svému předplatnému Azure. Pokud máte více předplatných, vyberte předplatné, které obsahuje vaši vyhledávací službu.

    az login
    
  3. Vytvořte $token objekt pro uložení přístupového tokenu.

    $token = az account get-access-token --resource https://search.azure.com/ --query accessToken --output tsv
    
  4. Vytvořte $headers objekt pro uložení tokenu a typu obsahu.

    $headers = @{
    'Authorization' = "Bearer $token"
    'Content-Type' = 'application/json' 
    'Accept' = 'application/json' }
    

    Záhlaví stačí nastavit jenom jednou pro každou relaci, ale musíte ho přidat do každého požadavku.

  5. Vytvořte $url objekt, který cílí na kolekci indexů ve vyhledávací službě. Nahraďte <YOUR-SEARCH-SERVICE> hodnotou, kterou jste získali v koncovém bodu Get.

    $url = "<YOUR-SEARCH-SERVICE>/indexes?api-version=2024-07-01&`$select=name"
    
  6. Spusťte Invoke-RestMethod, abyste odeslali požadavek GET do vyhledávací služby. Zahrnout ConvertTo-Json k zobrazení odpovědí ze služby.

    Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-Json
    

    Pokud je vaše služba prázdná a nemá žádné indexy, odpověď se podobá následujícímu příkladu. V opačném případě se zobrazí reprezentace definic indexu JSON.

    {
        "@odata.context":  "https://my-service.search.windows.net/$metadata#indexes",
        "value":  [
    
                  ]
    }
    

Vytvoření vyhledávacího indexu

Než přidáte obsah do služby Azure AI Search, musíte vytvořit index, který definuje, jak se obsah ukládá a strukturuje. Index je koncepčně podobný tabulce v relační databázi, ale je speciálně navržený pro operace hledání, jako je fulltextové vyhledávání.

Ve stejné relaci PowerShellu, kterou jste spustili v předchozí části, spusťte následující příkazy.

Vytvoření indexu:

  1. Vytvořte $body objekt pro definování schématu indexu.

    $body = @"
    {
        "name": "hotels-quickstart",  
        "fields": [
            {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true},
            {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false},
            {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"},
            {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
            {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true},
            {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true},
            {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true},
            {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true},
            {"name": "Address", "type": "Edm.ComplexType", 
                "fields": [
                {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true},
                {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}
            ]
         }
      ]
    }
    "@
    
  2. Aktualizujte $url objekt tak, aby cílil na nový index. Nahraďte <YOUR-SEARCH-SERVICE> hodnotou, kterou jste získali v koncovém bodu Get.

    $url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart?api-version=2024-07-01"
    
  3. Spusťte Invoke-RestMethod pro vytvoření indexu ve vaší vyhledávací službě.

    Invoke-RestMethod -Uri $url -Headers $headers -Method Put -Body $body | ConvertTo-Json
    

    Odpověď by měla obsahovat reprezentaci json schématu indexu.

O žádosti o vytvoření indexu

Tento úvod do používání zavolá indexy – vytvoření (REST API) k sestavení vyhledávacího indexu s názvem hotels-quickstart a jeho fyzických datových struktur ve vaší vyhledávací službě.

Kolekce fields ve schématu indexu definuje strukturu hotelových dokumentů. Každé pole obsahuje namedata typea atributy, které určují jeho chování při indexování a dotazech. Pole HotelId je označené jako klíč, který Azure AI Search vyžaduje k jedinečné identifikaci každého dokumentu v indexu.

Klíčové body schématu indexu:

  • Pomocí řetězcových polí (Edm.String) můžete číselná data prohledávat fulltextově. Jiné podporované datové typy, jako například Edm.Int32, jsou filtrovatelné, řaditelné, fasetovatelné a načitatelné, ale nedají se prohledávat.

  • Většina našich polí je jednoduchých datových typů, ale můžete definovat složité typy, které představují vnořená data, například Address pole.

  • Atributy polí určují povolené akce. Rozhraní REST API ve výchozím nastavení umožňují mnoho akcí. Například všechny řetězce jsou prohledávatelné a dohledatelné. S rozhraními REST API můžete používat pouze atributy, pokud potřebujete zakázat chování.

Načtení indexu

Nově vytvořené indexy jsou prázdné. Pokud chcete naplnit index a nastavit, aby byl prohledávatelný, musíte nahrát dokumenty JSON, které odpovídají schématu indexu.

Ve službě Azure AI Search slouží dokumenty jako vstupy pro indexování a výstupy pro dotazy. Pro zjednodušení tento rychlý začátek poskytuje ukázkové hotelové dokumenty jako vložený JSON. V produkčních scénářích se ale obsah často načítá z připojených zdrojů dat a transformuje se do FORMÁTU JSON pomocí indexerů.

Nahrání dokumentů do indexu:

  1. Vytvořte $body objekt pro uložení datové části JSON čtyř ukázkových dokumentů.

    $body = @"
        {
            "value": [
            {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
            "Category": "Boutique",
            "Tags": [ "view", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2022-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
            "Category": "Boutique",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2019-02-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "3",
            "HotelName": "Gastronomic Landscape Hotel",
            "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
            "Category": "Suite",
            "Tags": [ "restaurant", "bar", "continental breakfast" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.80,
            "Address": 
                {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
            "Category": "Boutique",
            "Tags": [ "concierge", "view", "air conditioning" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2020-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
                {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
                }
            }
          ]
        }
    "@
    
  2. Aktualizujte $url objekt tak, aby cílil na koncový bod indexování. Nahraďte <YOUR-SEARCH-SERVICE> hodnotou, kterou jste získali v koncovém bodu Get.

    $url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs/index?api-version=2024-07-01"
    
  3. Spuštěním příkazu Invoke-RestMethod odešlete žádost o nahrání do vyhledávací služby.

    Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Body $body | ConvertTo-Json
    

    Odpověď by měla obsahovat klíč a stav každého nahraného dokumentu.

O žádosti o nahrání

Tento rychlý start volá dokumenty – index (REST API) pro přidání čtyř ukázkových hotelových dokumentů do indexu. V porovnání s předchozím požadavkem je identifikátor URI rozšířen tak, aby zahrnoval kolekci docs a index operaci.

Každý dokument v value poli představuje hotel a obsahuje pole, která odpovídají schématu indexu. Parametr @search.action určuje operaci, která se má provést pro každý dokument. Náš příklad používá upload, který přidá dokument, pokud neexistuje nebo aktualizuje dokument, pokud existuje.

Dotazování indexu

Teď, když jsou dokumenty načtené do indexu, můžete pomocí fulltextového vyhledávání vyhledat konkrétní termíny nebo fráze v jejich polích.

Spuštění fulltextového dotazu na index:

  1. Aktualizujte $url objekt tak, aby určil parametry hledání. Nahraďte <YOUR-SEARCH-SERVICE> hodnotou, kterou jste získali v koncovém bodu Get.

    $url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=attached restaurant&searchFields=Description,Tags&$select=HotelId,HotelName,Tags,Description&$count=true'
    
  2. Spusťte Invoke-RestMethod pro odeslání dotazu do vyhledávací služby.

    Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-Json
    

    Odpověď by měla vypadat podobně jako v následujícím příkladu, který zobrazuje jeden odpovídající hotelový dokument, skóre relevance a vybraná pole.

    {
      "@odata.context": "https://my-service.search.windows.net/indexes('hotels-quickstart')/$metadata#docs(*)",
      "@odata.count": 1,
      "value": [
        {
          "@search.score": 0.5575875,
          "HotelId": "3",
          "HotelName": "Gastronomic Landscape Hotel",
          "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
          "Tags": "restaurant bar continental breakfast"
        }
      ]
    }
    

O požadavku na dotaz

Tento rychlý start volá dokumenty – vyhledávací příspěvek (REST API) k vyhledání hotelových dokumentů, které odpovídají vašim kritériím hledání. Identifikátor URI stále cílí na kolekci docs, ale operaci index už neobsahuje.

Požadavky fulltextového vyhledávání vždy obsahují search parametr, který obsahuje text dotazu. Text dotazu může obsahovat jeden nebo více termínů, frází nebo operátorů. Kromě searchtoho můžete zadat další parametry, které upřesní chování hledání a výsledky.

Náš dotaz vyhledá termíny "připojená restaurace" v Description polích Tags každého hotelového dokumentu. Parametr $select omezuje pole vrácená v odpovědi na HotelId, HotelName, Tagsa Description. Parametr $count požaduje celkový počet odpovídajících dokumentů.

Další příklady dotazů

Spuštěním následujících příkazů prozkoumejte syntaxi dotazu. Můžete provádět vyhledávání řetězců, používat $filter výrazy, omezit sady výsledků, vybrat konkrétní pole a další. Nezapomeňte nahradit <YOUR-SEARCH-SERVICE> hodnotou, kterou jste získali v koncovém bodu Get.

# Query example 1
# Search the index for the terms 'restaurant' and 'wifi'
# Return only the HotelName, Description, and Tags fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=restaurant wifi&$count=true&$select=HotelName,Description,Tags'

# Query example 2 
# Use a filter to find hotels rated 4 or higher
# Return only the HotelName and Rating fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=*&$filter=Rating gt 4&$select=HotelName,Rating'

# Query example 3
# Take the top two results
# Return only the HotelName and Category fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=boutique&$top=2&$select=HotelName,Category'

# Query example 4
# Sort by a specific field (Address/City) in ascending order
# Return only the HotelName, Address/City, Tags, and Rating fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=pool&$orderby=Address/City asc&$select=HotelName, Address/City, Tags, Rating'

V tomto rychlém startu použijete klientskou knihovnu Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání s ukázkovými daty pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Dokončený poznámkový blok si můžete stáhnout a spustit.

Požadavky

Požadavky pro Microsoft Entra ID

Pro doporučené ověřování bez klíčů s ID Microsoft Entra musíte:

  • Nainstalujte Azure CLI.

  • Přiřaďte uživatelskému účtu role Search Service Contributor a Search Index Data Contributor. Role můžete přiřadit na webu Azure Portal v části Řízení přístupu (IAM)>Přidat přiřazení role. Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Načtení informací o prostředcích

Abyste mohli aplikaci ověřit pomocí Search Azure AI, musíte načíst následující informace:

Název proměnné Hodnota
SEARCH_API_ENDPOINT Tuto hodnotu najdete na webu Azure Portal. Vyberte vyhledávací službu a pak v nabídce vlevo vyberte Přehled. Hodnota url v části Essentials je koncový bod, který potřebujete. Příkladem koncového bodu může být https://mydemo.search.windows.net.

Přečtěte si další informace o ověřování bez klíčů a nastavení proměnných prostředí.

Nastavení prostředí

Vzorový kód spustíte v poznámkovém bloku Jupyter. Proto musíte nastavit prostředí pro spouštění poznámkových bloků Jupyter.

  1. Stáhněte nebo zkopírujte ukázkový poznámkový blok z GitHubu.

  2. Otevřete poznámkový blok v editoru Visual Studio Code.

  3. Vytvořte nové prostředí Pythonu, které se použije k instalaci balíčků, které potřebujete pro účely tohoto kurzu.

    Důležité

    Neinstalujte balíčky do globální instalace Pythonu. Při instalaci balíčků Pythonu byste měli vždy používat virtuální prostředí nebo prostředí Conda, jinak můžete přerušit globální instalaci Pythonu.

    py -3 -m venv .venv
    .venv\scripts\activate
    

    Nastavení může trvat minutu. Pokud narazíte na problémy, prohlédni si prostředí Pythonu ve VS Code.

  4. Pokud je ještě nemáte, nainstalujte poznámkové bloky Jupyter a jádro IPythonu pro poznámkové bloky Jupyter.

    pip install jupyter
    pip install ipykernel
    python -m ipykernel install --user --name=.venv
    
  5. Vyberte jádro poznámkového bloku.

    1. V pravém horním rohu poznámkového bloku vyberte Vybrat jádro.
    2. Pokud se .venv zobrazí v seznamu, vyberte ho. Pokud ho nevidíte, vyberte Vybrat

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

V této části přidáte kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spuštěním programu zobrazíte výsledky v konzole. Podrobné vysvětlení kódu najdete v části s vysvětlením kódu .

  1. Ujistěte se, že je poznámkový blok otevřený v jádru .venv , jak je popsáno v předchozí části.

  2. Spuštěním první buňky kódu nainstalujte požadované balíčky, včetně azure-search-documents.

    ! pip install azure-search-documents==11.6.0b1 --quiet
    ! pip install azure-identity --quiet
    ! pip install python-dotenv --quiet
    
  3. Obsah druhé buňky kódu nahraďte následujícím kódem v závislosti na metodě ověřování.

    Poznámka:

    Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

    from azure.core.credentials import AzureKeyCredential
    from azure.identity import DefaultAzureCredential, AzureAuthorityHosts
    
    search_endpoint: str = "https://<Put your search service NAME here>.search.windows.net/"
    authority = AzureAuthorityHosts.AZURE_PUBLIC_CLOUD
    credential = DefaultAzureCredential(authority=authority)
    
    index_name: str = "hotels-quickstart-python"
    
  4. Odeberte následující dva řádky z buňky Vytvořit kód indexu. Přihlašovací údaje jsou již nastaveny v předchozí buňce kódu.

    from azure.core.credentials import AzureKeyCredential
    credential = AzureKeyCredential(search_api_key)
    
  5. Spuštěním buňky Vytvořit index kódu vytvořte vyhledávací index.

  6. Spusťte zbývající buňky kódu postupně, aby se načetly dokumenty a spouštěly dotazy.

Vysvětlení kódu

Vytvoření indexu

SearchIndexClient slouží k vytváření a správě indexů pro Azure AI Search. Každé pole je identifikováno a name má zadané type.

Každé pole má také řadu atributů indexu, které určují, jestli může Azure AI Search prohledávat, filtrovat, řadit a omezující vlastnosti pole. Většina polí je jednoduchých datových typů, ale některé, jako AddressType jsou složité typy, které umožňují vytvářet bohaté datové struktury v indexu. Další informace opodporovaných

Vytvoření datové části dokumentů a nahrání dokumentů

Použijte akci indexu pro typ operace, například nahrání nebo sloučení a nahrání. Dokumenty pocházejí z ukázky HotelsData na GitHubu.

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ů.

Použijte metodu vyhledávání třídy search.client.

Ukázkové dotazy v poznámkovém bloku jsou:

  • Základní dotaz: Provede prázdné hledání (search=*), vrátí neřaděný seznam (skóre hledání = 1,0) libovolných dokumentů. Vzhledem k tomu, že neexistují žádná kritéria, jsou ve výsledcích zahrnuty všechny dokumenty.
  • Dotaz termínů: Přidá do vyhledávacího výrazu celé termíny ("wifi"). Tento dotaz určuje, že výsledky obsahují pouze tato pole v select příkazu. Omezení polí, která se vrátí, minimalizuje množství dat odesílaných zpět přes drát a snižuje latenci vyhledávání.
  • Filtrovaný dotaz: Přidejte výraz filtru, který vrací pouze ty hotely s hodnocením větším než čtyři, seřazené sestupně.
  • Obory polí: Přidejte search_fields do oboru provádění dotazu na konkrétní pole.
  • Omezující vlastnosti: Vygenerujte omezující vlastnosti pro kladné shody nalezené ve výsledcích hledání. Neexistují žádné nulové shody. Pokud výsledky hledání neobsahují termín wifi, wifi se nezobrazí ve fasetové navigační struktuře.
  • Vyhledání dokumentu: Vrátí dokument na základě jeho klíče. Tato operace je užitečná, pokud chcete poskytnout podrobnou analýzu, když uživatel vybere položku ve výsledku hledání.
  • Automatické dokončování: Zadejte potenciální shody, protože uživatel zadá do vyhledávacího pole. Automatické dokončování používá modul pro návrhy (sg) ke zjištění, která pole obsahují potenciální shody pro žádosti s návrhy. V tomto rychlém startu jsou Tagstato pole , Address/City, Address/Country. Pokud chcete simulovat automatické dokončování, předejte písmena sa jako částečný řetězec. Metoda automatického dokončování SearchClient odesílá zpět potenciální shody termínů.

Odebrání indexu

Pokud jste s tímto indexem hotovi, můžete ho odstranit spuštěním buňky Vyčistit kód. Odstranění nepotřebných indexů uvolní místo pro procházení dalších rychlých startů a kurzů.

V tomto rychlém startu použijete rozhraní REST API služby Azure AI Search k vytvoření, načtení a dotazování indexu vyhledávání pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Konfigurace přístupu

Ke službě Azure AI Search se můžete připojit pomocí klíčů rozhraní API nebo ID Microsoft Entra s přiřazeními rolí. Klíče se snadněji spouštějí, ale role jsou bezpečnější.

Konfigurace doporučeného přístupu na základě role:

  1. Přihlaste se do Azure portálu a vyberte svou vyhledávací službu.

  2. V levém podokně vyberte Nastavení>Klíče.

  3. V části Řízení přístupu k rozhraní API vyberte Obě.

    Tato možnost umožňuje ověřování založené na klíčích i bez klíčů. Po přiřazení rolí se můžete vrátit k tomuto kroku a vybrat řízení přístupu na základě role.

  4. V levém podokně vyberte Řízení přístupu (IAM).

  5. Vyberte Přidat>Přiřadit roli.

  6. Přiřaďte roli Přispěvatel vyhledávací služby a Přispěvatel dat indexu vyhledávání k vašemu uživatelskému účtu.

Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Získání koncového bodu a tokenu

V další části zadáte následující koncový bod a token pro navázání připojení ke službě Azure AI Search. Tento postup předpokládá, že jste nakonfigurovali přístup na základě role.

Získání koncového bodu služby a tokenu:

  1. Přihlaste se do Azure portálu a vyberte svou vyhledávací službu.

  2. V levém podokně vyberte Přehled.

  3. Poznamenejte si adresu URL, která by měla být podobná https://my-service.search.windows.net.

  4. V místním systému otevřete terminál.

  5. Přihlaste se ke svému předplatnému Azure. Pokud máte více předplatných, vyberte předplatné, které obsahuje vaši vyhledávací službu.

    az login
    
  6. Poznamenejte si token Microsoft Entra.

    az account get-access-token --scope https://search.azure.com/.default
    

Nastavení souboru

Než budete moct volat rozhraní REST API do služby Azure AI Search, musíte vytvořit soubor pro uložení koncového bodu služby, ověřovacího tokenu a konečných požadavků. Rozšíření REST Client v editoru Visual Studio Code tuto úlohu podporuje.

Chcete-li připravit soubor žádosti:

  1. V místním systému otevřete Visual Studio Code.

  2. Vytvořte .rest soubor nebo .http soubor.

  3. Do souboru vložte následující zástupné symboly a požadavek.

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @token = PUT-YOUR-PERSONAL-IDENTITY-TOKEN-HERE
    
    ### List existing indexes by name
    GET {{baseUrl}}/indexes?api-version=2024-07-01  HTTP/1.1
        Authorization: Bearer {{token}}
    
  4. Nahraďte zástupné symboly @baseUrl a @token hodnotami, které jste získali v Získat konečný bod a token. Nepoužívejte uvozovky.

  5. V části ### List existing indexes by nameVyberte Možnost Odeslat žádost.

    V sousedním podokně by se měla zobrazit odpověď. Pokud máte existující indexy, jsou uvedené. V opačném případě je seznam prázdný. Pokud je 200 OKkód HTTP, jste připraveni na další kroky.

    Snímek obrazovky znázorňující klienta REST nakonfigurovaného pro požadavek vyhledávací služby

Vytvoření vyhledávacího indexu

Než přidáte obsah do služby Azure AI Search, musíte vytvořit index, který definuje, jak se obsah ukládá a strukturuje. Index je koncepčně podobný tabulce v relační databázi, ale je speciálně navržený pro operace hledání, jako je fulltextové vyhledávání.

Vytvoření indexu:

  1. Do souboru vložte následující požadavek.

    ### Create a new index
    POST {{baseUrl}}/indexes?api-version=2024-07-01  HTTP/1.1
        Content-Type: application/json
        Authorization: Bearer {{token}}
    
        {
            "name": "hotels-quickstart",  
            "fields": [
                {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true},
                {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false},
                {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"},
                {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true},
                {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true},
                {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true},
                {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true},
                {"name": "Address", "type": "Edm.ComplexType", 
                    "fields": [
                    {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true},
                    {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}
                    ]
                }
            ]
        }
    
  2. V části ### Create a new indexVyberte Možnost Odeslat žádost.

    Měli byste obdržet odpověď, HTTP/1.1 201 Created jejíž tělo obsahuje reprezentaci schématu indexu JSON.

O žádosti o vytvoření indexu

Tento úvod do používání zavolá indexy – vytvoření (REST API) k sestavení vyhledávacího indexu s názvem hotels-quickstart a jeho fyzických datových struktur ve vaší vyhledávací službě.

Kolekce fields ve schématu indexu definuje strukturu hotelových dokumentů. Každé pole obsahuje namedata typea atributy, které určují jeho chování při indexování a dotazech. Pole HotelId je označené jako klíč, který Azure AI Search vyžaduje k jedinečné identifikaci každého dokumentu v indexu.

Klíčové body schématu indexu:

  • Pomocí řetězcových polí (Edm.String) můžete číselná data prohledávat fulltextově. Jiné podporované datové typy, jako například Edm.Int32, jsou filtrovatelné, řaditelné, fasetovatelné a načitatelné, ale nedají se prohledávat.

  • Většina našich polí je jednoduchých datových typů, ale můžete definovat složité typy, které představují vnořená data, například Address pole.

  • Atributy polí určují povolené akce. Rozhraní REST API ve výchozím nastavení umožňují mnoho akcí. Například všechny řetězce jsou prohledávatelné a dohledatelné. S rozhraními REST API můžete používat pouze atributy, pokud potřebujete zakázat chování.

Načtení indexu

Nově vytvořené indexy jsou prázdné. Pokud chcete naplnit index a nastavit, aby byl prohledávatelný, musíte nahrát dokumenty JSON, které odpovídají schématu indexu.

Ve službě Azure AI Search slouží dokumenty jako vstupy pro indexování a výstupy pro dotazy. Pro zjednodušení tento rychlý začátek poskytuje ukázkové hotelové dokumenty jako vložený JSON. V produkčních scénářích se ale obsah často načítá z připojených zdrojů dat a transformuje se do FORMÁTU JSON pomocí indexerů.

Nahrání dokumentů do indexu:

  1. Do souboru vložte následující požadavek.

    ### Upload documents
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version=2024-07-01  HTTP/1.1
        Content-Type: application/json
        Authorization: Bearer {{token}}
    
        {
            "value": [
            {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
            "Category": "Boutique",
            "Tags": [ "view", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2022-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
             "Category": "Boutique",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2019-02-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "3",
            "HotelName": "Gastronomic Landscape Hotel",
            "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
            "Category": "Suite",
            "Tags": [ "restaurant", "bar", "continental breakfast" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.80,
            "Address": 
                {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
            "Category": "Luxury",
            "Tags": [ "concierge", "view", "air conditioning" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2020-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
                {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
                }
            }
          ]
        }
    
  2. V části ### Upload documentsVyberte Možnost Odeslat žádost.

    Měli byste obdržet odpověď, HTTP/1.1 200 OK jejíž text obsahuje klíč a stav každého nahraného dokumentu.

O žádosti o nahrání

Tento rychlý start volá dokumenty – index (REST API) pro přidání čtyř ukázkových hotelových dokumentů do indexu. V porovnání s předchozím požadavkem je identifikátor URI rozšířen tak, aby zahrnoval kolekci docs a index operaci.

Každý dokument v value poli představuje hotel a obsahuje pole, která odpovídají schématu indexu. Parametr @search.action určuje operaci, která se má provést pro každý dokument. Náš příklad používá upload, který přidá dokument, pokud neexistuje nebo aktualizuje dokument, pokud existuje.

Dotazování indexu

Teď, když jsou dokumenty načtené do indexu, můžete pomocí fulltextového vyhledávání vyhledat konkrétní termíny nebo fráze v jejich polích.

Spuštění fulltextového dotazu na index:

  1. Do souboru vložte následující požadavek.

    ### Run a query
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
      {
          "search": "attached restaurant",
          "select": "HotelId, HotelName, Tags, Description",
          "searchFields": "Description, Tags",
          "count": true
      }
    
  2. V části ### Run a queryVyberte Možnost Odeslat žádost.

    Měli byste obdržet HTTP/1.1 200 OK odpověď, která je podobná následujícímu příkladu, jež zobrazuje jeden odpovídající hotelový dokument, jeho skóre relevance a vybraná pole.

    {
      "@odata.context": "https://my-service.search.windows.net/indexes('hotels-quickstart')/$metadata#docs(*)",
      "@odata.count": 1,
      "value": [
        {
          "@search.score": 0.5575875,
          "HotelId": "3",
          "HotelName": "Gastronomic Landscape Hotel",
          "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel\u2019s restaurant services.",
          "Tags": [
            "restaurant",
            "bar",
            "continental breakfast"
          ]
        }
      ]
    }
    

O požadavku na dotaz

Tento rychlý start volá dokumenty – vyhledávací příspěvek (REST API) k vyhledání hotelových dokumentů, které odpovídají vašim kritériím hledání. Identifikátor URI teď cílí na /docs/search operaci.

Požadavky fulltextového vyhledávání vždy obsahují search parametr, který obsahuje text dotazu. Text dotazu může obsahovat jeden nebo více termínů, frází nebo operátorů. Kromě searchtoho můžete zadat další parametry, které upřesní chování hledání a výsledky.

Náš dotaz vyhledá termíny "připojená restaurace" v Description polích Tags každého hotelového dokumentu. Parametr select omezuje pole vrácená v odpovědi na HotelId, HotelName, Tagsa Description. Parametr count požaduje celkový počet odpovídajících dokumentů.

V tomto rychlém startu použijete klientskou knihovnu Azure.Search.Documents k vytvoření, načtení a dotazování indexu vyhledávání s ukázkovými daty pro fulltextové vyhledávání. Fulltextové vyhledávání používá Apache Lucene k indexování a dotazům a algoritmu řazení BM25 pro bodování výsledků.

V tomto rychlém startu se k naplnění indexu používají fiktivní hotelová data z úložiště azure-search-sample-data .

Návod

Zdrojový kód si můžete stáhnout, abyste mohli začít s hotovým projektem, nebo si podle těchto kroků vytvořte vlastní.

Požadavky

Požadavky pro Microsoft Entra ID

Pro doporučené ověřování bez klíčů s ID Microsoft Entra musíte:

  • Nainstalujte Azure CLI.

  • Přiřaďte uživatelskému účtu role Search Service Contributor a Search Index Data Contributor. Role můžete přiřadit na webu Azure Portal v části Řízení přístupu (IAM)>Přidat přiřazení role. Další informace najdete v tématu Připojení k Azure AI Search pomocí rolí.

Načtení informací o prostředcích

Abyste mohli aplikaci ověřit pomocí Search Azure AI, musíte načíst následující informace:

Název proměnné Hodnota
SEARCH_API_ENDPOINT Tuto hodnotu najdete na webu Azure Portal. Vyberte vyhledávací službu a pak v nabídce vlevo vyberte Přehled. Hodnota url v části Essentials je koncový bod, který potřebujete. Příkladem koncového bodu může být https://mydemo.search.windows.net.

Přečtěte si další informace o ověřování bez klíčů a nastavení proměnných prostředí.

Nastavení

  1. Vytvořte novou složku full-text-quickstart , která bude obsahovat aplikaci, a otevřete v této složce Visual Studio Code pomocí následujícího příkazu:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Vytvořte následující package.json příkaz:

    npm init -y
    
  3. package.json Aktualizujte na ECMAScript následujícím příkazem:

    npm pkg set type=module
    
  4. Nainstalujte klientskou knihovnu Azure AI Search (Azure.Search.Documents) pro JavaScript pomocí:

    npm install @azure/search-documents
    
  5. Pro doporučené ověřování bez hesla nainstalujte klientskou knihovnu Azure Identity pomocí:

    npm install @azure/identity
    

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

V předchozí části nastavení jste nainstalovali klientskou knihovnu Azure AI Search a další závislosti.

V této části přidáte kód pro vytvoření indexu vyhledávání, načtení s dokumenty a spouštění dotazů. Spuštěním programu zobrazíte výsledky v konzole. Podrobné vysvětlení kódu najdete v části s vysvětlením kódu .

Ukázkový kód v tomto rychlém startu používá PRO doporučené ověřování bez klíčů ID Microsoft Entra. Pokud dáváte přednost použití klíče rozhraní API, můžete objekt nahradit DefaultAzureCredential objektem AzureKeyCredential .

const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
  1. Vytvořte nový soubor s názvem index.ts a vložte do index.ts následující kód:

    // Import from the @azure/search-documents library
    import {
        SearchIndexClient,
        SearchClient,
        SearchFieldDataType,
        AzureKeyCredential,
        odata,
        SearchIndex
    } from "@azure/search-documents";
    
    // Import from the Azure Identity library
    import { DefaultAzureCredential } from "@azure/identity";
    
    // Importing the hotels sample data
    import hotelData from './hotels.json' assert { type: "json" };
    
    // Load the .env file if it exists
    import * as dotenv from "dotenv";
    dotenv.config();
    
    // Defining the index definition
    const indexDefinition: SearchIndex = {
    	"name": "hotels-quickstart",
    	"fields": [
    		{
    			"name": "HotelId",
    			"type": "Edm.String" as SearchFieldDataType,
    			"key": true,
    			"filterable": true
    		},
    		{
    			"name": "HotelName",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": false,
    			"sortable": true,
    			"facetable": false
    		},
    		{
    			"name": "Description",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": false,
    			"sortable": false,
    			"facetable": false,
    			"analyzerName": "en.lucene"
    		},
    		{
    			"name": "Category",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Tags",
    			"type": "Collection(Edm.String)",
    			"searchable": true,
    			"filterable": true,
    			"sortable": false,
    			"facetable": true
    		},
    		{
    			"name": "ParkingIncluded",
    			"type": "Edm.Boolean",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "LastRenovationDate",
    			"type": "Edm.DateTimeOffset",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Rating",
    			"type": "Edm.Double",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Address",
    			"type": "Edm.ComplexType",
    			"fields": [
    				{
    					"name": "StreetAddress",
    					"type": "Edm.String" as SearchFieldDataType,
    					"filterable": false,
    					"sortable": false,
    					"facetable": false,
    					"searchable": true
    				},
    				{
    					"name": "City",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "StateProvince",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "PostalCode",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "Country",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				}
    			]
    		}
    	],
    	"suggesters": [
    		{
    			"name": "sg",
    			"searchMode": "analyzingInfixMatching",
    			"sourceFields": [
    				"HotelName"
    			]
    		}
    	]
    };
    
    async function main() {
    
    	// Your search service endpoint
    	const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
    
    	// Use the recommended keyless credential instead of the AzureKeyCredential credential.
    	const credential = new DefaultAzureCredential();
    	//const credential = new AzureKeyCredential(Your search service admin key);
    
    	// Create a SearchIndexClient to send create/delete index commands
    	const searchIndexClient: SearchIndexClient = new SearchIndexClient(
    		searchServiceEndpoint,
    		credential
    	);
    
    	// Creating a search client to upload documents and issue queries
    	const indexName: string  = "hotels-quickstart";
        const searchClient: SearchClient<any> = searchIndexClient.getSearchClient(indexName);
    
        console.log('Checking if index exists...');
        await deleteIndexIfExists(searchIndexClient, indexName);
    
        console.log('Creating index...');
        let index: SearchIndex = await searchIndexClient.createIndex(indexDefinition);
        console.log(`Index named ${index.name} has been created.`);
    
        console.log('Uploading documents...');
        let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
        console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `);
    
        // waiting one second for indexing to complete (for demo purposes only)
        sleep(1000);
    
        console.log('Querying the index...');
        console.log();
        await sendQueries(searchClient);
    }
    
    async function deleteIndexIfExists(searchIndexClient: SearchIndexClient, indexName: string) {
        try {
            await searchIndexClient.deleteIndex(indexName);
            console.log('Deleting index...');
        } catch {
            console.log('Index does not exist yet.');
        }
    }
    
    async function sendQueries(searchClient: SearchClient<any>) {
        // Query 1
        console.log('Query #1 - search everything:');
        let searchOptions: any = {
            includeTotalCount: true,
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        let searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log(`Result count: ${searchResults.count}`);
        console.log();
    
    
        // Query 2
        console.log('Query #2 - search with filter, orderBy, and select:');
        let state = 'FL';
        searchOptions = {
            filter: odata`Address/StateProvince eq ${state}`,
            orderBy: ["Rating desc"],
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        searchResults = await searchClient.search("wifi", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 3
        console.log('Query #3 - limit searchFields:');
        searchOptions = {
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("sublime palace", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 4
        console.log('Query #4 - limit searchFields and use facets:');
        searchOptions = {
            facets: ["Category"],
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 5
        console.log('Query #5 - Lookup document:');
        let documentResult = await searchClient.getDocument('3');
        console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);
        console.log();
    }
    
    function sleep(ms: number) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    main().catch((err) => {
        console.error("The sample encountered an error:", err);
    });
    
  2. Vytvořte soubor s názvem hotels.json a vložte do hotels.json následující kód:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Stay-Kay City Hotel",
                "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times 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.",
                "Category": "Boutique",
                "Tags": ["view", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "2022-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "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. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "2019-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Gastronomic Landscape Hotel",
                "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Category": "Suite",
                "Tags": ["restaurant, "bar", "continental breakfast"],
                "ParkingIncluded": "true",
                "LastRenovationDate": "2015-09-20T00:00:00Z",
                "Rating": 4.8,
                "Address": {
                    "StreetAddress": "3393 Peachtree Rd",
                    "City": "Atlanta",
                    "StateProvince": "GA",
                    "PostalCode": "30326"
                }
            },
            {
                "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 Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "air conditioning"],
                "ParkingIncluded": true,
                "LastRenovationDate": "2020-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. tsconfig.json Vytvořte soubor pro transpilování kódu TypeScript a zkopírujte následující kód pro ECMAScript.

    {
        "compilerOptions": {
          "module": "NodeNext",
          "target": "ES2022", // Supports top-level await
          "moduleResolution": "NodeNext",
          "skipLibCheck": true, // Avoid type errors from node_modules
          "strict": true // Enable strict type-checking options
        },
        "include": ["*.ts"]
    }
    
  4. Transpilovat z TypeScriptu do JavaScriptu.

    tsc
    
  5. Přihlaste se k Azure pomocí následujícího příkazu:

    az login
    
  6. Spusťte kód JavaScriptu pomocí následujícího příkazu:

    node index.js
    

Vysvětlení kódu

Vytvoření indexu

Vytvořte soubor hotels_quickstart_index.json. Tento soubor definuje, jak Azure AI Search funguje s dokumenty, které načtete v dalším kroku. Každé pole je identifikováno a name má zadané type. Každé pole má také řadu atributů indexu, které určují, jestli může Azure AI Search prohledávat, filtrovat, řadit a omezující vlastnosti pole. Většina polí je jednoduchých datových typů, ale některé, jako AddressType jsou složité typy, které umožňují vytvářet bohaté datové struktury v indexu. Další informace opodporovaných

Chceme importovat hotels_quickstart_index.json , aby hlavní funkce přistupovala k definici indexu.

import indexDefinition from './hotels_quickstart_index.json';

interface HotelIndexDefinition {
    name: string;
    fields: SimpleField[] | ComplexField[];
    suggesters: SearchSuggester[];
};
const hotelIndexDefinition: HotelIndexDefinition = indexDefinition as HotelIndexDefinition;

V rámci hlavní funkce pak vytvoříme , SearchIndexClientkterá se použije k vytváření a správě indexů pro Azure AI Search.

const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));

Dále chceme odstranit index, pokud už existuje. Tato operace je běžným postupem pro testovací nebo ukázkový kód.

Provedeme to tak, že definujeme jednoduchou funkci, která se pokusí odstranit index.

async function deleteIndexIfExists(indexClient: SearchIndexClient, indexName: string): Promise<void> {
    try {
        await indexClient.deleteIndex(indexName);
        console.log('Deleting index...');
    } catch {
        console.log('Index does not exist yet.');
    }
}

Ke spuštění funkce extrahujeme název indexu z definice indexu indexNameindexClient a předáme deleteIndexIfExists() funkci spolu s funkcí.

// Getting the name of the index from the index definition
const indexName: string = hotelIndexDefinition.name;

console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);

Potom jsme připraveni vytvořit index pomocí createIndex() metody.

console.log('Creating index...');
let index = await indexClient.createIndex(hotelIndexDefinition);

console.log(`Index named ${index.name} has been created.`);

Nahrání dokumentů

Ve službě Azure AI Search jsou dokumenty datové struktury, které jsou vstupy indexování a výstupy z dotazů. Tato data můžete odeslat do indexu nebo použít indexer. V tomto případě nahrajeme dokumenty do indexu prostřednictvím kódu programu.

Vstupy dokumentů můžou být řádky v databázi, objekty blob v úložišti objektů blob nebo jako v této ukázce dokumenty JSON na disku. Můžete si stáhnout hotels.json nebo vytvořit vlastní soubor hotels.json s následujícím obsahem:

Podobně jako u indexDefinition je potřeba importovat hotels.json také do horní části index.ts , aby k datům bylo možné přistupovat v hlavní funkci.

import hotelData from './hotels.json';

interface Hotel {
    HotelId: string;
    HotelName: string;
    Description: string;
    Category: string;
    Tags: string[];
    ParkingIncluded: string | boolean;
    LastRenovationDate: string;
    Rating: number;
    Address: {
        StreetAddress: string;
        City: string;
        StateProvince: string;
        PostalCode: string;
    };
};

const hotels: Hotel[] = hotelData["value"];

Abychom mohli data indexovat do vyhledávacího indexu, musíme teď vytvořit .SearchClient SearchIndexClient Zatímco se používá k vytvoření a správě indexu, SearchClient slouží k nahrání dokumentů a dotazování indexu.

Existují dva způsoby, jak vytvořit SearchClient. První možností je vytvořit úplně SearchClient od začátku:

 const searchClient = new SearchClient<Hotel>(endpoint, indexName, new AzureKeyCredential(apiKey));

Alternativně můžete použít getSearchClient() metodu SearchIndexClient vytvoření SearchClient:

const searchClient = indexClient.getSearchClient<Hotel>(indexName);

Teď, když je klient definovaný, nahrajte dokumenty do indexu vyhledávání. V tomto případě použijeme metodu mergeOrUploadDocuments() , která nahraje dokumenty nebo je sloučí s existujícím dokumentem, pokud už existuje dokument se stejným klíčem. Pak zkontrolujte, jestli operace proběhla úspěšně, protože existuje alespoň první dokument.

console.log("Uploading documents...");
const indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotels);

console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);

Spusťte program znovu pomocí tsc && node index.tspříkazu . Měli byste vidět trochu odlišnou sadu zpráv od zpráv, které jste viděli v kroku 1. Tentokrát existuje index a měla by se zobrazit zpráva o jejím odstranění, než aplikace vytvoří nový index a publikuje do něj data.

Než spustíme dotazy v dalším kroku, definujte funkci, která má program čekat na jednu sekundu. To se provádí jenom pro účely testování/ukázky, aby se zajistilo dokončení indexování a dostupnost dokumentů v indexu pro naše dotazy.

function sleep(ms: number): Promise<void> {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

Pokud chcete, aby program čekal na jednu sekundu sleep , zavolejte funkci:

sleep(1000);

Prohledání indexu

Když jste vytvořili index a nahráli jste dokumenty, můžete do indexu odesílat dotazy. V této části pošleme do indexu vyhledávání pět různých dotazů, abychom vám ukázali různé části funkcí dotazů, které jsou vám k dispozici.

Dotazy jsou napsané ve sendQueries() funkci, kterou voláme v hlavní funkci následujícím způsobem:

await sendQueries(searchClient);

Dotazy se odesílají pomocí search() metody searchClient. Prvním parametrem je hledaný text a druhý parametr určuje možnosti hledání.

Příklad dotazu 1

První dotaz vyhledá *, což je ekvivalent pro hledání všeho a vybere tři pole v indexu. Osvědčeným postupem je pouze select pole, která potřebujete, protože stažení nepotřebných dat může do dotazů přidat latenci.

U searchOptions tohoto dotazu je includeTotalCount také nastavena hodnota true, která vrátí počet nalezených odpovídajících výsledků.

async function sendQueries(
    searchClient: SearchClient<Hotel>
): Promise<void> {

    // Query 1
    console.log('Query #1 - search everything:');
    const selectFields: SearchFieldArray<Hotel> = [
        "HotelId",
        "HotelName",
        "Rating",
    ];
    const searchOptions1 = { 
        includeTotalCount: true, 
        select: selectFields 
    };

    let searchResults = await searchClient.search("*", searchOptions1);
    for await (const result of searchResults.results) {
        console.log(`${JSON.stringify(result.document)}`);
    }
    console.log(`Result count: ${searchResults.count}`);

    // remaining queries go here
}

Zbývající níže uvedené dotazy by se také měly přidat do sendQueries() funkce. Jsou zde odděleny pro čitelnost.

Příklad dotazu 2

V dalším dotazu určíme hledaný termín "wifi" a zahrneme také filtr, který vrátí pouze výsledky, ve kterých je stav roven 'FL'. Výsledky jsou také objednány hotelovým hotelem Rating.

console.log('Query #2 - search with filter, orderBy, and select:');
let state = 'FL';
const searchOptions2 = {
    filter: odata`Address/StateProvince eq ${state}`,
    orderBy: ["Rating desc"],
    select: selectFields
};
searchResults = await searchClient.search("wifi", searchOptions2);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Příklad dotazu 3

Dále je hledání omezeno na jedno prohledávatelné pole pomocí parametru searchFields . Tento přístup je skvělou možností, jak zefektivnit dotaz, pokud víte, že vás zajímají jenom shody v určitých polích.

console.log('Query #3 - limit searchFields:');
const searchOptions3 = {
    select: selectFields,
    searchFields: ["HotelName"] as const
};

searchResults = await searchClient.search("Sublime Palace", searchOptions3);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Příklad dotazu 4

Další běžnou možností zahrnutí do dotazu je facets. Fasety umožňují poskytovat samoobslužné přechody k podrobnostem z výsledků v uživatelském rozhraní. Výsledky omezujících vlastností se dají v podokně výsledků převést na zaškrtávací políčka.

console.log('Query #4 - limit searchFields and use facets:');
const searchOptions4 = {
    facets: ["Category"],
    select: selectFields,
    searchFields: ["HotelName"] as const
};

searchResults = await searchClient.search("*", searchOptions4);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Příklad dotazu 5

Poslední dotaz používá getDocument() metodu searchClient. Díky tomu můžete dokument efektivně načíst podle jeho klíče.

console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)

Souhrn dotazů

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í searchClient.search metody. Vyhledávací dotaz lze předat v řetězci searchText , zatímco výraz filtru lze předat ve filter vlastnosti SearchOptions třídy. Pokud chcete filtrovat bez hledání, stačí předat searchText parametr search metody "*". Pokud chcete hledat bez filtrování, nechejte filter vlastnost nenasazenou nebo vůbec nepředávejte SearchOptions instanci.

Vyčistěte zdroje

Při práci ve vlastním předplatném je vhodné dokončit projekt určením, jestli stále potřebujete prostředky, které jste vytvořili. Prostředky, které zůstaly spuštěné, vám můžou stát peníze. Prostředky můžete odstranit jednotlivě nebo můžete odstranit skupinu prostředků a odstranit tak celou sadu prostředků.

Na webu Azure Portal můžete najít a spravovat prostředky tak, že v levém podokně vyberete Všechny prostředky nebo skupiny prostředků .

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 webu Azure Portal můžete odstranit, abyste zůstali pod limitem.