Megosztás a következőn keresztül:


Rövid útmutató: Teljes szöveges keresés az Azure SDK-k használatával

Megtudhatja, hogyan hozhat létre, tölthet be és kérdezhet le keresési indexet az Azure.Search.Documents ügyféloldali kódtár használatával a teljes szöveges keresés mintaadataival. A teljes szöveges keresés az Apache Lucene-t használja az indexeléshez és a lekérdezésekhez, valamint egy BM25 rangsorolási algoritmust a pontozási eredményekhez.

Ez a rövid útmutató létrehoz és lekérdez egy kisméretű, négy szállodára vonatkozó adatokat tartalmazó rövid útmutató-indexet.

Tipp.

Letöltheti a forráskódot, hogy befejezett projekttel kezdjen, vagy kövesse az alábbi lépéseket a saját létrehozásához.

Előfeltételek

A Microsoft Entra ID előfeltételei

A Microsoft Entra-azonosítóval javasolt kulcs nélküli hitelesítéshez a következőket kell elvégeznie:

Erőforrásadatok lekérése

Az alkalmazás Azure AI-Search szolgáltatás történő hitelesítéséhez le kell kérnie a következő adatokat:

Változó neve Érték
SEARCH_API_ENDPOINT Ez az érték az Azure Portalon található. Válassza ki a keresési szolgáltatást, majd a bal oldali menüben válassza az Áttekintés lehetőséget. Az Essentials alatt található URL-érték a szükséges végpont. A végpontok például a következőképpen nézhetnek ki: https://mydemo.search.windows.net.

További információ a kulcs nélküli hitelesítésről és a környezeti változók beállításáról.

Beállítás

  1. Hozzon létre egy új mappát full-text-quickstart , amely tartalmazza az alkalmazást, és nyissa meg a Visual Studio Code-ot abban a mappában a következő paranccsal:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Hozzon létre egy új konzolalkalmazást a következő paranccsal:

    dotnet new console
    
  3. Telepítse az Azure AI Search ügyfélkódtárát (Azure.Search.Documents) a .NET-hez a következőkkel:

    dotnet add package Azure.Search.Documents
    
  4. A Microsoft Entra ID-val javasolt kulcs nélküli hitelesítéshez telepítse az Azure.Identity csomagot a következőkkel:

    dotnet add package Azure.Identity
    
  5. A Microsoft Entra ID-val javasolt kulcs nélküli hitelesítéshez jelentkezzen be az Azure-ba a következő paranccsal:

    az login
    

Keresési index létrehozása, betöltése és lekérdezése

Az előző beállítási szakaszban létrehozott egy új konzolalkalmazást, és telepítette az Azure AI Search ügyfélkódtárát.

Ebben a szakaszban kódot ad hozzá egy keresési index létrehozásához, dokumentumokkal való betöltéséhez és lekérdezések futtatásához. Futtassa a programot az eredmények megtekintéséhez a konzolon. A kód részletes magyarázatát a kódszakaszban találja.

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra AzureKeyCredential .

Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
  1. A Program.cs illessze be a következő kódot. Szerkessze a serviceName keresési szolgáltatás nevét és apiKey a rendszergazdai API-kulcsot tartalmazó változókat.

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

    using System;
    using System.Text.Json.Serialization;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            [SimpleField(IsKey = true, IsFilterable = true)]
            public string HotelId { get; set; }
    
            [SearchableField(IsSortable = true)]
            public string HotelName { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
            public string Description { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
            [JsonPropertyName("Description_fr")]
            public string DescriptionFr { get; set; }
    
            [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public string Category { get; set; }
    
            [SearchableField(IsFilterable = true, IsFacetable = true)]
            public string[] Tags { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public bool? ParkingIncluded { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public DateTimeOffset? LastRenovationDate { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public double? Rating { get; set; }
    
            [SearchableField]
            public Address Address { get; set; }
        }
    }
    
  3. Hozzon létre egy Hotel.cs nevű új fájlt, és illessze be a következő kódot egy szállodai dokumentum szerkezetének meghatározásához. A mező attribútumai határozzák meg, hogyan használják azt egy alkalmazásban. Az attribútumot például minden olyan mezőhöz hozzá kell rendelni, IsFilterable amely egy szűrőkifejezést támogat.

    using System;
    using System.Text.Json.Serialization;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            [SimpleField(IsKey = true, IsFilterable = true)]
            public string HotelId { get; set; }
    
            [SearchableField(IsSortable = true)]
            public string HotelName { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
            public string Description { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)]
            [JsonPropertyName("Description_fr")]
            public string DescriptionFr { get; set; }
    
            [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public string Category { get; set; }
    
            [SearchableField(IsFilterable = true, IsFacetable = true)]
            public string[] Tags { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public bool? ParkingIncluded { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public DateTimeOffset? LastRenovationDate { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public double? Rating { get; set; }
    
            [SearchableField]
            public Address Address { get; set; }
        }
    }
    
  4. Hozzon létre egy Address.cs nevű új fájlt, és illessze be a következő kódot egy címdokumentum szerkezetének meghatározásához.

    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. Hozzon létre egy Hotel.Methods.cs nevű új fájlt, és illessze be a következő kódot az osztály felülbírálásának Hotel meghatározásáhozToString().

    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(DescriptionFr))
                {
                    builder.AppendFormat("Description (French): {0}\n", DescriptionFr);
                }
    
                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. Hozzon létre egy Address.Methods.cs nevű új fájlt, és illessze be a következő kódot az osztály felülbírálásának Address definiálásáhozToString().

    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. Hozza létre és futtassa az alkalmazást a következő paranccsal:

    dotnet run
    

A kimenet tartalmazza a Console.WriteLine üzeneteit, a lekérdezési információk és eredmények hozzáadásával.

A kód ismertetése

Az előző szakaszokban létrehozott egy új konzolalkalmazást, és telepítette az Azure AI Search ügyfélkódtárát. Hozzáadta a kódot egy keresési index létrehozásához, a dokumentumokba való betöltéséhez és a lekérdezések futtatásához. Futtatta a programot az eredmények megtekintéséhez a konzolon.

Ebben a szakaszban bemutatjuk a konzolalkalmazáshoz hozzáadott kódot.

Keresési ügyfél létrehozása

A Program.cs két ügyfelet hozott létre:

Mindkét ügyfélnek szüksége van a keresési szolgáltatásvégpontra és az erőforrás-információk szakaszban korábban ismertetett hitelesítő adatokra .

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra 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 . . . 
}

Index létrehozása

Ez a rövid útmutató létrehoz egy hotelindexet, amelyet a szálloda adataival tölt be, és lekérdezéseket hajt végre. Ebben a lépésben definiálja az index mezőit. Minden meződefiníció tartalmaz egy nevet, adattípust és attribútumot, amely meghatározza a mező használatát.

Ebben a példában az Azure.Search.Documents kódtár szinkron metódusait használjuk az egyszerűség és az olvashatóság érdekében. Éles forgatókönyvek esetén azonban aszinkron módszereket kell használnia az alkalmazás skálázható és rugalmas állapotának megőrzéséhez. Például a CreateIndexAsyncet használná a CreateIndex helyett.

A struktúrák meghatározása

Létrehozott két segédosztályt, Hotel.cs és Address.cs egy szállodai dokumentum struktúrájának és címének meghatározásához. Az Hotel osztály tartalmazza a szállodaazonosító, a név, a leírás, a kategória, a címkék, a parkolás, a felújítás dátuma, az értékelés és a cím mezőit. Az Address osztály tartalmazza a cím, a város, az állam/tartomány, az irányítószám és az ország/régió mezőit.

Az Azure.Search.Documents ügyfélkódtárban a SearchableField és a SimpleField használatával egyszerűsítheti a meződefiníciókat. Mindkettő a SearchField származéka, és potenciálisan egyszerűsítheti a kódot:

  • SimpleField bármilyen adattípus lehet, mindig nem kereshető (teljes szöveges keresési lekérdezések esetén figyelmen kívül hagyva), és lekérdezhető (nem rejtett). Más attribútumok alapértelmezés szerint ki vannak kapcsolva, de engedélyezhetők. Használhat SimpleField dokumentumazonosítókat vagy mezőket, amelyeket csak szűrőkben, aspektusokban vagy pontozási profilokban használ. Ha igen, mindenképpen alkalmazza a forgatókönyvhöz szükséges attribútumokat, például IsKey = true egy dokumentumazonosítót. További információ: SimpleFieldAttribute.cs a forráskódban.

  • SearchableField sztringnek kell lennie, és mindig kereshető és lekérdezhető. Más attribútumok alapértelmezés szerint ki vannak kapcsolva, de engedélyezhetők. Mivel ez a mezőtípus kereshető, támogatja a szinonimákat és az elemző tulajdonságainak teljes kiegészítését. További információ: SearchableFieldAttribute.cs a forráskódban.

Akár az alapszintű SearchField API-t, akár az egyik segédmodellt használja, explicit módon engedélyeznie kell a szűrési, aspektus- és rendezési attribútumokat. Az IsFilterable, az IsSortable és az IsFacetable attribútumot például explicit módon kell hozzárendelni az előző mintában látható módon.

Keresési index létrehozása

A Program.cs létrehoz egy SearchIndex-objektumot , majd meghívja a CreateIndex metódust az index kifejezéséhez a keresési szolgáltatásban. Az index tartalmaz egy SearchSuggestert is, amely engedélyezi az automatikus kiegészítést a megadott mezőkön.

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

Dokumentumok betöltése

Az Azure AI Search a szolgáltatásban tárolt tartalmakon keres. Ebben a lépésben olyan JSON-dokumentumokat tölt be, amelyek megfelelnek a létrehozott szállodaindexnek.

Az Azure AI Searchben a keresési dokumentumok olyan adatstruktúrák, amelyek egyaránt bemenetek az indexeléshez és a lekérdezésekből származó kimenetekhez. A külső adatforrásból származó dokumentumbemenetek lehetnek egy adatbázis sorai, blobok a Blob Storage-ban vagy a lemezen lévő JSON-dokumentumok. Ebben a példában egy parancsikont hozunk létre, és négy szállodához ágyazunk be JSON-dokumentumokat magában a kódban.

Dokumentumok feltöltésekor IndexDocumentsBatch objektumot kell használnia. Az IndexDocumentsBatch objektumok műveletek gyűjteményét tartalmazzák, amelyek mindegyike tartalmaz egy dokumentumot és egy tulajdonságot, amely közli az Azure AI Search szolgáltatással, hogy milyen műveletet kell végrehajtania (feltöltés, egyesítés, törlés és mergeOrUpload).

A Program.cs egy dokumentum- és indexműveleteket tartalmazó tömböt hoz létre, majd átadja a tömböt.IndexDocumentsBatch Az alábbi dokumentumok megfelelnek a szállodai osztály által meghatározott, a hotels-quickstart indexnek.

// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
    IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(
            new Hotel()
            {
                HotelId = "1",
                HotelName = "Stay-Kay City Hotel",
                Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
                Category = "Boutique",
                Tags = new[] { "pool", "air conditioning", "concierge" },
                ParkingIncluded = false,
                LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
                Rating = 3.6,
                Address = new Address()
                {
                    StreetAddress = "677 5th Ave",
                    City = "New York",
                    StateProvince = "NY",
                    PostalCode = "10022",
                    Country = "USA"
                }
            }),
        // REDACTED FOR BREVITY
}

Az IndexDocumentsBatch objektum inicializálása után elküldheti azt az indexbe a SearchClient objektum IndexDocuments meghívásával.

A Dokumentumok betöltése a SearchClient Main()használatával történik, de a művelethez rendszergazdai jogosultságok is szükségesek a szolgáltatáshoz, amely általában a SearchIndexClienthez van társítva. A művelet beállításának egyik módja a SearchClient beolvasása SearchIndexClient (searchIndexClient ebben a példában).

SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);

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

Mivel van egy konzolalkalmazásunk, amely az összes parancsot egymás után futtatja, 2 másodperces várakozási időt adunk hozzá az indexelés és a lekérdezések között.

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

A 2 másodperces késleltetés kompenzálja az indexelést, amely aszinkron, így az összes dokumentum indexelhető a lekérdezések végrehajtása előtt. A késésben történő kódolás általában csak demókban, tesztekben és mintaalkalmazásokban szükséges.

Keresés az indexekben

Az első dokumentum indexelése után azonnal lekérheti a lekérdezési eredményeket, de az index tényleges tesztelésének várnia kell, amíg az összes dokumentum indexel.

Ez a szakasz két funkciót ad hozzá: lekérdezési logikát és eredményeket. Lekérdezésekhez használja a Keresés metódust. Ez a metódus a keresési szöveget (a lekérdezési sztringet) és más beállításokat használja.

A SearchResults osztály az eredményeket jelöli.

A Program.cs a WriteDocuments metódus a keresési eredményeket a konzolra nyomtatja.

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

1. lekérdezési példa

A RunQueries metódus lekérdezéseket hajt végre, és eredményeket ad vissza. Az eredmények hotelobjektumok. Ez a minta a metódus aláírását és az első lekérdezést mutatja be. Ez a lekérdezés bemutatja azt a Select paramétert, amely lehetővé teszi az eredmény megírását a dokumentum kijelölt mezőivel.

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

2. lekérdezési példa

A második lekérdezésben keressen rá egy kifejezésre, adjon hozzá egy szűrőt, amely kiválasztja a 4-nél nagyobb minősítést tartalmazó dokumentumokat, majd csökkenő sorrendben rendezi az értékelés szerint. A szűrő egy logikai kifejezés, amelyet egy index IsFilterable mezőinek alapján értékel ki a program. A szűrő lekérdezések tartalmazhatnak vagy kizárnak értékeket. Ezért nincs relevanciapont társítva egy szűrő lekérdezéshez.

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

3. lekérdezési példa

A harmadik lekérdezés egy teljes szöveges keresési művelet adott mezőkre való hatókörét mutatja be searchFields.

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

options = new SearchOptions()
{
    SearchFields = { "Tags" }
};

options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Tags");

response = searchClient.Search<Hotel>("pool", options);
WriteDocuments(response);

4. lekérdezési példa

A negyedik lekérdezés bemutatja facets, hogy milyen strukturált navigációs szerkezetek hozhatók létre.

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

5. lekérdezési példa

Az ötödik lekérdezésben adjon vissza egy adott dokumentumot. A dokumentumkeresés általában egy eredményhalmaz eseményére OnClick adott válasz.

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

6. lekérdezési példa

Az utolsó lekérdezés az automatikus kiegészítés szintaxisát jeleníti meg, szimulálva az sa részleges felhasználói bemenetét, amely az indexben definiált javaslathoz társított forrásmezőkben két lehetséges egyezésre oldható fel.

// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");

var autoresponse = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);

Lekérdezések összegzése

Az előző lekérdezések több módon is egyeztetik a kifejezéseket a lekérdezésekben: teljes szöveges keresés, szűrők és automatikus kiegészítés.

A teljes szöveges keresést és a szűrőket a SearchClient.Search metódussal hajtja végre. A keresési lekérdezések átadhatók a sztringbensearchText, míg egy szűrőkifejezés átadható a SearchOptions osztály Szűrő tulajdonságában. Ha keresés nélkül szeretne szűrni, egyszerűen adja meg "*" a searchTextKeresési módszer paraméterét. Ha szűrés nélkül szeretne keresni, hagyja meg a Filter tulajdonságot, vagy egyáltalán ne adja át a példányt SearchOptions .

Megtudhatja, hogyan hozhat létre, tölthet be és kérdezhet le keresési indexet az Azure.Search.Documents ügyféloldali kódtár használatával a teljes szöveges keresés mintaadataival. A teljes szöveges keresés az Apache Lucene-t használja az indexeléshez és a lekérdezésekhez, valamint egy BM25 rangsorolási algoritmust a pontozási eredményekhez.

Ez a rövid útmutató létrehoz és lekérdez egy kisméretű, négy szállodára vonatkozó adatokat tartalmazó rövid útmutató-indexet.

Tipp.

Letöltheti a forráskódot, hogy befejezett projekttel kezdjen, vagy kövesse az alábbi lépéseket a saját létrehozásához.

Előfeltételek

A Microsoft Entra ID előfeltételei

A Microsoft Entra-azonosítóval javasolt kulcs nélküli hitelesítéshez a következőket kell elvégeznie:

Erőforrásadatok lekérése

Az alkalmazás Azure AI-Search szolgáltatás történő hitelesítéséhez le kell kérnie a következő adatokat:

Változó neve Érték
SEARCH_API_ENDPOINT Ez az érték az Azure Portalon található. Válassza ki a keresési szolgáltatást, majd a bal oldali menüben válassza az Áttekintés lehetőséget. Az Essentials alatt található URL-érték a szükséges végpont. A végpontok például a következőképpen nézhetnek ki: https://mydemo.search.windows.net.

További információ a kulcs nélküli hitelesítésről és a környezeti változók beállításáról.

Beállítás

A rövid útmutatóban szereplő minta a Java-futtatókörnyezettel működik. Telepítsen egy Java-fejlesztőkészletet, például az Azul Zulu OpenJDK-t. Az OpenJDK Microsoft buildjének vagy az előnyben részesített JDK-nak is működnie kell.

  1. Telepítse az Apache Maven-t. Ezután futtassa mvn -v a sikeres telepítés megerősítéséhez.

  2. Hozzon létre egy új pom.xml fájlt a projekt gyökerében, és másolja bele a következő kódot:

    <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. Telepítse a függőségeket, beleértve az Azure AI Search ügyféloldali kódtárát (Azure.Search.Documents) a Java és az Azure Identity java-ügyfélkódtárához a következőkkel:

    mvn clean dependency:copy-dependencies
    
  4. A Microsoft Entra ID-val javasolt kulcs nélküli hitelesítéshez jelentkezzen be az Azure-ba a következő paranccsal:

    az login
    

Keresési index létrehozása, betöltése és lekérdezése

Az előző beállítási szakaszban telepítette az Azure AI Search ügyfélkódtárat és más függőségeket.

Ebben a szakaszban kódot ad hozzá egy keresési index létrehozásához, dokumentumokkal való betöltéséhez és lekérdezések futtatásához. Futtassa a programot az eredmények megtekintéséhez a konzolon. A kód részletes magyarázatát a kódszakaszban találja.

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra AzureKeyCredential .

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Hozzon létre egy App.java nevű új fájlt, és illessze be a következő kódot a App.java:

    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 = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.";
            hotel.descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "pool", "air conditioning", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1970, 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.";
            hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "pool", "free wifi", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1979, 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 Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.";
            hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.";
            hotel.category = "Resort and Spa";
            hotel.tags = new String[] { "air conditioning", "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 Palace is part of a lovingly restored 1800 palace.";
            hotel.descriptionFr = "Le Sublime Palace Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Palace fait partie d'un Palace 1800 restauré avec amour.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "concierge", "view", "24-hour front desk service" };
            hotel.parkingIncluded = true;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1960, 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. Hozzon létre egy Hotel.java nevű új fájlt, és illessze be a következő kódot a Hotel.java:

    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;
    
        /**
         * French description
         */
        @JsonProperty("DescriptionFr")
        @SearchableField(analyzerName = "fr.lucene")
        public String descriptionFr;
    
        /**
         * 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. Hozzon létre egy Address.java nevű új fájlt, és illessze be a következő kódot a Address.java:

    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. Futtassa az új konzolalkalmazást:

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

A kód ismertetése

Az előző szakaszokban létrehozott egy új konzolalkalmazást, és telepítette az Azure AI Search ügyfélkódtárát. Hozzáadta a kódot egy keresési index létrehozásához, a dokumentumokba való betöltéséhez és a lekérdezések futtatásához. Futtatta a programot az eredmények megtekintéséhez a konzolon.

Ebben a szakaszban bemutatjuk a konzolalkalmazáshoz hozzáadott kódot.

Keresési ügyfél létrehozása

A App.java két ügyfelet hozott létre:

  • A SearchIndexClient létrehozza az indexet.
  • A SearchClient betölt és lekérdez egy meglévő indexet.

Mindkét ügyfélnek szüksége van a keresési szolgáltatásvégpontra és az erőforrás-információk szakaszban korábban ismertetett hitelesítő adatokra.

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra 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 . . . 
}

Index létrehozása

Ez a rövid útmutató létrehoz egy hotelindexet, amelyet a szálloda adataival tölt be, és lekérdezéseket hajt végre. Ebben a lépésben definiálja az index mezőit. Minden meződefiníció tartalmaz egy nevet, adattípust és attribútumot, amely meghatározza a mező használatát.

Ebben a példában az Azure.Search.Documents kódtár szinkron metódusait használjuk az egyszerűség és az olvashatóság érdekében. Éles forgatókönyvek esetén azonban aszinkron módszereket kell használnia az alkalmazás skálázható és rugalmas állapotának megőrzéséhez. Például a CreateIndexAsyncet használná a CreateIndex helyett.

A struktúrák meghatározása

Létrehozott két segédosztályt, Hotel.java és Address.java egy szállodai dokumentum struktúrájának és címének meghatározásához. A Hotel osztály tartalmazza a szállodaazonosító, a név, a leírás, a kategória, a címkék, a parkolás, a felújítás dátuma, az értékelés és a cím mezőit. A Cím osztály tartalmazza az utcacím, a város, az állam/tartomány, az irányítószám és az ország/régió mezőit.

Az Azure.Search.Documents ügyfélkódtárban a SearchableField és a SimpleField használatával egyszerűsítheti a meződefiníciókat.

  • SimpleField bármilyen adattípus lehet, mindig nem kereshető (teljes szöveges keresési lekérdezések esetén figyelmen kívül hagyva), és lekérdezhető (nem rejtett). Más attribútumok alapértelmezés szerint ki vannak kapcsolva, de engedélyezhetők. Előfordulhat, hogy a SimpleFieldet csak szűrőkben, aspektusokban vagy pontozási profilokban használt dokumentumazonosítókhoz vagy mezőkhöz használja. Ha igen, mindenképpen alkalmazzon minden olyan attribútumot, amely a forgatókönyvhöz szükséges, például isKey = igaz a dokumentumazonosítóhoz.
  • SearchableField sztringnek kell lennie, és mindig kereshető és lekérdezhető. Más attribútumok alapértelmezés szerint ki vannak kapcsolva, de engedélyezhetők. Mivel ez a mezőtípus kereshető, támogatja a szinonimákat és az elemző tulajdonságainak teljes kiegészítését.

Akár az alapszintű SearchField API-t, akár az egyik segédmodellt használja, explicit módon engedélyeznie kell a szűrési, aspektus- és rendezési attribútumokat. Például, isFilterable, isSortableés isFacetable explicit módon kell hozzárendelni, ahogy az előző példában is látható.

Keresési index létrehozása

Ebben App.javaaz esetben létrehoz egy SearchIndex objektumot a main metódusban, majd meghívja a createOrUpdateIndex metódust az index létrehozásához a keresési szolgáltatásban. Az index tartalmaz egy SearchSuggester automatikus kiegészítést is a megadott mezőkön.

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

Dokumentumok betöltése

Az Azure AI Search a szolgáltatásban tárolt tartalmakon keres. Ebben a lépésben olyan JSON-dokumentumokat tölt be, amelyek megfelelnek a létrehozott szállodaindexnek.

Az Azure AI Searchben a keresési dokumentumok olyan adatstruktúrák, amelyek egyaránt bemenetek az indexeléshez és a lekérdezésekből származó kimenetekhez. A külső adatforrásból származó dokumentumbemenetek lehetnek egy adatbázis sorai, blobok a Blob Storage-ban vagy a lemezen lévő JSON-dokumentumok. Ebben a példában egy parancsikont hozunk létre, és négy szállodához ágyazunk be JSON-dokumentumokat magában a kódban.

Dokumentumok feltöltésekor IndexDocumentsBatch objektumot kell használnia. Az IndexDocumentsBatch objektumok az IndexActions gyűjteményét tartalmazzák, amelyek mindegyike tartalmaz egy dokumentumot és egy tulajdonságot, amely közli az Azure AI Search szolgáltatással, hogy milyen műveletet kell végrehajtania (feltöltés, egyesítés, törlés és mergeOrUpload).

Ebben a fájlban App.javadokumentumokat és indexműveleteket hozhat létre, majd továbbíthatja őket a következőnek IndexDocumentsBatch: Az alábbi dokumentumok megfelelnek a szállodai osztály által meghatározott, a hotels-quickstart indexnek.

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 = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.";
    hotel.descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.";
    hotel.category = "Boutique";
    hotel.tags = new String[] { "pool", "air conditioning", "concierge" };
    hotel.parkingIncluded = false;
    hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1970, 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");
    }
}

Az objektum inicializálása IndexDocumentsBatch után elküldheti azt az indexbe az objektum indexdokumentsSearchClient meghívásával.

A Dokumentumok betöltése a SearchClient main()használatával történik, de a művelethez rendszergazdai jogosultságok is szükségesek a szolgáltatáshoz, amely általában a SearchIndexClienthez van társítva. A művelet beállításának egyik módja a SearchClient beolvasása SearchIndexClient (searchIndexClient ebben a példában).

uploadDocuments(searchClient);

Mivel van egy konzolalkalmazásunk, amely az összes parancsot egymás után futtatja, 2 másodperces várakozási időt adunk hozzá az indexelés és a lekérdezések között.

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

A 2 másodperces késleltetés kompenzálja az indexelést, amely aszinkron, így az összes dokumentum indexelhető a lekérdezések végrehajtása előtt. A késésben történő kódolás általában csak demókban, tesztekben és mintaalkalmazásokban szükséges.

Keresés az indexekben

Az első dokumentum indexelése után azonnal lekérheti a lekérdezési eredményeket, de az index tényleges tesztelésének várnia kell, amíg az összes dokumentum indexel.

Ez a szakasz két funkciót ad hozzá: lekérdezési logikát és eredményeket. Lekérdezésekhez használja a Keresés metódust. Ez a metódus a keresési szöveget (a lekérdezési sztringet) és más beállításokat használja.

Ebben App.javaa metódus a WriteDocuments keresési eredményeket a konzolon nyomtatja ki.

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

1. lekérdezési példa

A RunQueries metódus lekérdezéseket hajt végre, és eredményeket ad vissza. Az eredmények hotelobjektumok. Ez a minta a metódus aláírását és az első lekérdezést mutatja be. Ez a lekérdezés bemutatja azt a Select paramétert, amely lehetővé teszi az eredmény megírását a dokumentum kijelölt mezőivel.

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

2. lekérdezési példa

A második lekérdezésben keressen rá egy kifejezésre, adjon hozzá egy szűrőt, amely kiválasztja a 4-nél nagyobb minősítést tartalmazó dokumentumokat, majd csökkenő sorrendben rendezi az értékelés szerint. A szűrő egy logikai kifejezés, amelyet egy index mezői értékelnek isFilterable ki. A szűrő lekérdezések tartalmazhatnak vagy kizárnak értékeket. Ezért nincs relevanciapont társítva egy szűrő lekérdezéshez.

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

3. lekérdezési példa

A harmadik lekérdezés egy teljes szöveges keresési művelet adott mezőkre való hatókörét mutatja be searchFields.

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

4. lekérdezési példa

A negyedik lekérdezés bemutatja facets, hogy milyen strukturált navigációs szerkezetek hozhatók létre.

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

5. lekérdezési példa

Az ötödik lekérdezésben adjon vissza egy adott dokumentumot.

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

6. lekérdezési példa

Az utolsó lekérdezés az automatikus kiegészítés szintaxisát jeleníti meg, szimulálva az s részleges felhasználói bemenetét, amely két lehetséges egyezésre oldódik fel az sourceFields indexben definiált javaslatotevőhöz társítva.

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

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

Lekérdezések összegzése

Az előző lekérdezések több módon is egyeztetik a kifejezéseket a lekérdezésekben: teljes szöveges keresés, szűrők és automatikus kiegészítés.

A teljes szöveges keresés és a szűrők a SearchClient.search metódussal hajthatók végre. A keresési lekérdezések átadhatók a sztringben searchText , míg egy szűrőkifejezés átadható a filterSearchOptions osztály tulajdonságában. Keresés nélküli szűréshez egyszerűen adja meg a "*" értéket a searchTextsearch metódus paraméteréhez. Ha szűrés nélkül szeretne keresni, hagyja meg a filter tulajdonságot, vagy egyáltalán ne adja át a példányt SearchOptions .

Megtudhatja, hogyan hozhat létre, tölthet be és kérdezhet le keresési indexet az Azure.Search.Documents ügyféloldali kódtár használatával a teljes szöveges keresés mintaadataival. A teljes szöveges keresés az Apache Lucene-t használja az indexeléshez és a lekérdezésekhez, valamint egy BM25 rangsorolási algoritmust a pontozási eredményekhez.

Ez a rövid útmutató létrehoz és lekérdez egy kisméretű, négy szállodára vonatkozó adatokat tartalmazó rövid útmutató-indexet.

Tipp.

Letöltheti a forráskódot, hogy befejezett projekttel kezdjen, vagy kövesse az alábbi lépéseket a saját létrehozásához.

Előfeltételek

A Microsoft Entra ID előfeltételei

A Microsoft Entra-azonosítóval javasolt kulcs nélküli hitelesítéshez a következőket kell elvégeznie:

Erőforrásadatok lekérése

Az alkalmazás Azure AI-Search szolgáltatás történő hitelesítéséhez le kell kérnie a következő adatokat:

Változó neve Érték
SEARCH_API_ENDPOINT Ez az érték az Azure Portalon található. Válassza ki a keresési szolgáltatást, majd a bal oldali menüben válassza az Áttekintés lehetőséget. Az Essentials alatt található URL-érték a szükséges végpont. A végpontok például a következőképpen nézhetnek ki: https://mydemo.search.windows.net.

További információ a kulcs nélküli hitelesítésről és a környezeti változók beállításáról.

Beállítás

  1. Hozzon létre egy új mappát full-text-quickstart , amely tartalmazza az alkalmazást, és nyissa meg a Visual Studio Code-ot abban a mappában a következő paranccsal:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Hozza létre a package.json következő paranccsal:

    npm init -y
    
  3. Telepítse az Azure AI Search ügyfélkódtárát (Azure.Search.Documents) JavaScripthez a következőkkel:

    npm install @azure/search-documents
    
  4. Az ajánlott jelszó nélküli hitelesítéshez telepítse az Azure Identity ügyfélkódtárat a következőkkel:

    npm install @azure/identity
    

Keresési index létrehozása, betöltése és lekérdezése

Az előző beállítási szakaszban telepítette az Azure AI Search ügyfélkódtárat és más függőségeket.

Ebben a szakaszban kódot ad hozzá egy keresési index létrehozásához, dokumentumokkal való betöltéséhez és lekérdezések futtatásához. Futtassa a programot az eredmények megtekintéséhez a konzolon. A kód részletes magyarázatát a kódszakaszban találja.

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra AzureKeyCredential .

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Hozzon létre egy index.js nevű új fájlt, és illessze be a következő kódot a index.js:

    // 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 cliff", 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. Hozzon létre egy hotels.json nevű fájlt, és illessze be a következő kódot hotels.json:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Secret Point Motel",
                "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                "Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
                "Category": "Boutique",
                "Tags": ["pool", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "1970-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "HotelId": "2",
                "HotelName": "Twin Dome Motel",
                "Description": "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
                "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "1979-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Triple Landscape Hotel",
                "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                "Category": "Resort and Spa",
                "Tags": ["air conditioning", "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 Cliff Hotel",
                "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
                "Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "24-hour front desk service"],
                "ParkingIncluded": true,
                "LastRenovationDate": "1960-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. Hozzon létre egy hotels_quickstart_index.json nevű fájlt, és illessze be a következő kódot hotels_quickstart_index.json:

    {
    	"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"
    			]
    		}
    	]
    }
    
  4. Jelentkezzen be az Azure-ba a következő paranccsal:

    az login
    
  5. Futtassa a JavaScript-kódot a következő paranccsal:

    node index.js
    

A kód ismertetése

Index létrehozása

A hotels_quickstart_index.json fájl határozza meg, hogyan működik az Azure AI Search a következő lépésben betöltődő dokumentumokkal. Az egyes mezőket egy name adott mező azonosítja, és rendelkezik egy megadott typemezővel. Minden mező indexattribútumok sorozatával is rendelkezik, amelyek meghatározzák, hogy az Azure AI Search képes-e keresni, szűrni, rendezni és kezelni a mezőt. A mezők többsége egyszerű adattípus, de néhány olyan összetett típus, amely AddressType lehetővé teszi, hogy gazdag adatstruktúrákat hozzon létre az indexben. A támogatott adattípusokról és indexattribútumokról az Index létrehozása (REST) című témakörben olvashat bővebben.

Az indexdefinícióval a index.js tetején szeretnénk importálni hotels_quickstart_index.json, hogy a fő függvény hozzáférhessen az indexdefinícióhoz.

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

A fő függvényen belül létrehozunk egy SearchIndexClient, az Azure AI Search indexeinek létrehozására és kezelésére szolgáló parancsot.

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

Ezután törölni szeretnénk az indexet, ha már létezik. Ez a művelet a tesztelési/demókódok gyakori gyakorlata.

Ehhez definiálunk egy egyszerű függvényt, amely megpróbálja törölni az indexet.

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

A függvény futtatásához kinyerjük az index nevét az indexdefinícióból, és átadjuk a indexName függvénynekdeleteIndexIfExists().indexClient

const indexName = indexDefinition["name"];

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

Ezután készen állunk az index metódussal való létrehozására createIndex() .

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

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

Dokumentumok betöltése

Az Azure AI Searchben a dokumentumok olyan adatstruktúrák, amelyek egyaránt bemenetek az indexeléshez és a lekérdezésekből származó kimenetekhez. Ezeket az adatokat leküldheti az indexbe, vagy használhat indexelőt. Ebben az esetben programozott módon leküldjük a dokumentumokat az indexbe.

A dokumentumbemenetek lehetnek egy adatbázis sorai, blobok a Blob Storage-ban, vagy a mintában szereplő JSON-dokumentumok a lemezen. A művelethez hasonlóan a indexDefinitionindex.js tetején is importálnunk hotels.json kell, hogy az adatok elérhetők legyenek a fő függvényünkben.

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

Ha adatokat szeretne indexelni a keresési indexbe, létre kell hoznunk egy SearchClient. Bár az SearchIndexClient indexek létrehozására és kezelésére szolgál, a SearchClient dokumentumok feltöltésére és az index lekérdezésére szolgál.

Kétféleképpen hozhat létre .SearchClient Az első lehetőség a nulláról történő létrehozás SearchClient :

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

Másik lehetőségként a getSearchClient() következő metódus SearchIndexClient használatával is létrehozhatja a következőt SearchClient:

const searchClient = indexClient.getSearchClient(indexName);

Az ügyfél definiálása után töltse fel a dokumentumokat a keresési indexbe. Ebben az esetben a metódust mergeOrUploadDocuments() használjuk, amely feltölti a dokumentumokat, vagy egyesíti őket egy meglévő dokumentummal, ha már létezik ugyanazzal a kulccsal rendelkező dokumentum.

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

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

Keresés az indexekben

Egy index létrehozásával és a feltöltött dokumentumokkal lekérdezéseket küldhet az indexnek. Ebben a szakaszban öt különböző lekérdezést küldünk a keresési indexbe, hogy bemutassuk az Ön számára elérhető különböző lekérdezési funkciókat.

A lekérdezések egy sendQueries() függvényben vannak megírva, amelyet a fő függvényben hívunk meg az alábbiak szerint:

await sendQueries(searchClient);

A rendszer a lekérdezéseket a search() következő módszerrel küldi searchClientel: . Az első paraméter a keresési szöveg, a második pedig a keresési beállításokat adja meg.

1. lekérdezési példa

Az első lekérdezés minden *kereséssel egyenértékű, és az index három mezőjét választja ki. Ajánlott csak a szükséges mezőket használni select , mert a szükségtelen adatok visszakérése késést okozhat a lekérdezésekben.

A searchOptions lekérdezés értéke is a következőre truevan includeTotalCount állítva, amely a talált találatok számát adja vissza.

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
}

Az alább ismertetett többi lekérdezést is hozzá kell adni a sendQueries() függvényhez. Itt külön vannak elválasztva az olvashatóság érdekében.

2. lekérdezési példa

A következő lekérdezésben megadjuk a keresési kifejezést "wifi" , és egy szűrőt is belefoglalunk, amely csak olyan eredményeket ad vissza, ahol az állapot egyenlő 'FL'. Az eredményeket a szálloda is rendezi 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)}`);
}

3. lekérdezési példa

Ezután a keresés egyetlen kereshető mezőre korlátozódik a searchFields paraméter használatával. Ez a megközelítés nagyszerű lehetőség arra, hogy hatékonyabbá tegye a lekérdezést, ha tudja, hogy csak bizonyos mezőkben lévő egyezések érdeklik.

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

4. lekérdezési példa

Egy másik gyakori lehetőség a lekérdezésbe való belefoglalás.facets Az aspektusok segítségével szűrőket hozhat létre a felhasználói felületen, így a felhasználók könnyen megismerhetik, hogy milyen értékekre szűrhetnek le.

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

5. lekérdezési példa

A végső lekérdezés a getDocument()searchClient. Így hatékonyan lekérhet egy dokumentumot a kulcsával.

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

Lekérdezések összegzése

Az előző lekérdezések több módon is egyeztetik a kifejezéseket a lekérdezésekben: teljes szöveges keresés, szűrők és automatikus kiegészítés.

A metódussal searchClient.search teljes szöveges keresést és szűrőket hajtunk végre. A keresési lekérdezések átadhatók a sztringben searchText , míg egy szűrőkifejezés átadható az filterSearchOptions osztály tulajdonságában. Keresés nélküli szűréshez egyszerűen adja meg a "*" értéket a searchTextsearch metódus paraméteréhez. Ha szűrés nélkül szeretne keresni, hagyja meg a filter tulajdonságot, vagy egyáltalán ne adja át a példányt SearchOptions .

Megtudhatja, hogyan hozhat létre, tölthet be és kérdezhet le keresési indexet az Azure.Search.Documents ügyféloldali kódtár használatával a teljes szöveges keresés mintaadataival. A teljes szöveges keresés az Apache Lucene-t használja az indexeléshez és a lekérdezésekhez, valamint egy BM25 rangsorolási algoritmust a pontozási eredményekhez.

Ez a rövid útmutató létrehoz és lekérdez egy kisméretű, négy szállodára vonatkozó adatokat tartalmazó rövid útmutató-indexet.

Tipp.

Letöltheti és futtathatja a kész jegyzetfüzetet.

Előfeltételek

A Microsoft Entra ID előfeltételei

A Microsoft Entra-azonosítóval javasolt kulcs nélküli hitelesítéshez a következőket kell elvégeznie:

Erőforrásadatok lekérése

Az alkalmazás Azure AI-Search szolgáltatás történő hitelesítéséhez le kell kérnie a következő adatokat:

Változó neve Érték
SEARCH_API_ENDPOINT Ez az érték az Azure Portalon található. Válassza ki a keresési szolgáltatást, majd a bal oldali menüben válassza az Áttekintés lehetőséget. Az Essentials alatt található URL-érték a szükséges végpont. A végpontok például a következőképpen nézhetnek ki: https://mydemo.search.windows.net.

További információ a kulcs nélküli hitelesítésről és a környezeti változók beállításáról.

Saját környezet beállítása

A mintakódot egy Jupyter-jegyzetfüzetben futtatja. Ezért be kell állítania a környezetet a Jupyter-notebookok futtatásához.

  1. Töltse le vagy másolja a mintajegyzetfüzetet a GitHubról.

  2. Nyissa meg a jegyzetfüzetet a Visual Studio Code-ban.

  3. Hozzon létre egy új Python-környezetet az oktatóanyaghoz szükséges csomagok telepítéséhez.

    Fontos

    Ne telepítsen csomagokat a globális Python-telepítésbe. Python-csomagok telepítésekor mindig használjon virtuális vagy conda környezetet, különben megszakíthatja a Python globális telepítését.

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

    A beállítás eltarthat egy percig. Ha problémákba ütközik, tekintse meg a Python-környezeteket a VS Code-ban.

  4. Telepítse a Jupyter-jegyzetfüzeteket és a Jupyter-jegyzetfüzetekhez készült IPython Kernelt, ha még nem rendelkezik velük.

    pip install jupyter
    pip install ipykernel
    python -m ipykernel install --user --name=.venv
    
  5. Válassza ki a jegyzetfüzet kernelét.

    1. A jegyzetfüzet jobb felső sarkában válassza a Kernel kiválasztása lehetőséget.
    2. Ha megjelenik .venv a listában, jelölje ki. Ha nem látja, válassza a Másik Kernel>Python-környezet kiválasztása>.venv lehetőséget.

Keresési index létrehozása, betöltése és lekérdezése

Ebben a szakaszban kódot ad hozzá egy keresési index létrehozásához, dokumentumokkal való betöltéséhez és lekérdezések futtatásához. Futtassa a programot az eredmények megtekintéséhez a konzolon. A kód részletes magyarázatát a kódszakaszban találja.

  1. Győződjön meg arról, hogy a jegyzetfüzet nyitva van a .venv kernelben az előző szakaszban leírtak szerint.

  2. Futtassa az első kódcellát a szükséges csomagok, köztük az azure-search-documents telepítéséhez.

    ! pip install azure-search-documents==11.6.0b1 --quiet
    ! pip install azure-identity --quiet
    ! pip install python-dotenv --quiet
    
  3. Cserélje le a második kódcella tartalmát a következő kódra a hitelesítési módszertől függően.

    Feljegyzés

    A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra 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. Távolítsa el az alábbi két sort az indexkód létrehozása cellából. A hitelesítő adatok már be vannak állítva az előző kódcellában.

    from azure.core.credentials import AzureKeyCredential
    credential = AzureKeyCredential(search_api_key)
    
  5. Keresési index létrehozásához futtassa az Indexkód létrehozása cellát.

  6. Futtassa a többi kódcellát egymás után a dokumentumok betöltéséhez és a lekérdezések futtatásához.

A kód ismertetése

Index létrehozása

SearchIndexClient az Azure AI Search indexeinek létrehozására és kezelésére szolgál. Az egyes mezőket egy name adott mező azonosítja, és rendelkezik egy adott typemezővel.

Minden mező indexattribútumok sorozatával is rendelkezik, amelyek meghatározzák, hogy az Azure AI Search képes-e keresni, szűrni, rendezni és kezelni a mezőt. A mezők többsége egyszerű adattípus, de néhány olyan összetett típus, amely AddressType lehetővé teszi, hogy gazdag adatstruktúrákat hozzon létre az indexben. A támogatott adattípusokról és indexattribútumokról az Index létrehozása (REST) című témakörben olvashat bővebben.

Hasznos adatok létrehozása és dokumentumok feltöltése

A művelettípushoz használjon indexműveletet, például feltöltést vagy egyesítést és feltöltést. A dokumentumok a GitHub HotelsData-mintájából származnak.

Keresés az indexekben

Az első dokumentum indexelése után azonnal lekérheti a lekérdezési eredményeket, de az index tényleges tesztelésének várnia kell, amíg az összes dokumentum indexel.

Használja a search.client osztály keresési módszerét.

A jegyzetfüzetben található minta lekérdezések a következők:

  • Alapszintű lekérdezés: Üres keresést hajt végre (search=*a keresési pontszám = 1,0) tetszőleges dokumentumokból álló üres listát ad vissza. Mivel nincsenek feltételek, minden dokumentum szerepel az eredmények között.
  • Kifejezéses lekérdezés: Egész kifejezéseket ad hozzá a keresési kifejezéshez ("wifi"). Ez a lekérdezés azt határozza meg, hogy az eredmények csak azokat a mezőket tartalmazzák az select utasításban. A visszaküldött mezők korlátozása minimálisra csökkenti a vezetéken visszaküldött adatok mennyiségét, és csökkenti a keresési késést.
  • Szűrt lekérdezés: Adjon hozzá egy szűrőkifejezést, amely csak a négynél nagyobb minősítésű szállodákat adja vissza csökkenő sorrendbe rendezve.
  • Mezős hatókörkezelés: Hozzáadás search_fields a hatókör-lekérdezés végrehajtásához adott mezőkhöz.
  • Aspektusok: A keresési eredményekben található pozitív egyezések aspektusainak létrehozása. Nincsenek nulla egyezések. Ha a keresési eredmények nem tartalmazzák a wifi kifejezést, akkor a wifi nem jelenik meg az arculati navigációs struktúrában.
  • Dokumentum keresése: Egy dokumentum visszaadása a kulcs alapján. Ez a művelet akkor hasznos, ha részletezni szeretné, ha egy felhasználó kiválaszt egy elemet egy keresési eredményben.
  • Automatikus kiegészítés: Adja meg a lehetséges találatokat, amikor a felhasználó be van típusok a keresőmezőbe. Az automatikus kiegészítés egy javaslatot (sg) használ annak megismerésére, hogy mely mezők tartalmaznak lehetséges egyezéseket a javaslattevő kérésekhez. Ebben a rövid útmutatóban ezek a mezők a következőkTags: , Address/CityAddress/Country. Az automatikus kiegészítés szimulálásához adja meg az sa betűket részleges sztringként. A SearchClient automatikus kiegészítési metódusa visszaküldi a lehetséges kifejezés-egyezéseket.

Az index eltávolítása

Ha befejezte ezt az indexet, törölheti azt a Clean up kódcella futtatásával. A szükségtelen indexek törlése helyet szabadít fel a gyorsútmutatók és oktatóanyagok végiglépéséhez.

Megtudhatja, hogyan hozhat létre, tölthet be és kérdezhet le keresési indexet az Azure.Search.Documents ügyféloldali kódtár használatával a teljes szöveges keresés mintaadataival. A teljes szöveges keresés az Apache Lucene-t használja az indexeléshez és a lekérdezésekhez, valamint egy BM25 rangsorolási algoritmust a pontozási eredményekhez.

Ez a rövid útmutató létrehoz és lekérdez egy kisméretű, négy szállodára vonatkozó adatokat tartalmazó rövid útmutató-indexet.

Tipp.

Letöltheti a forráskódot, hogy befejezett projekttel kezdjen, vagy kövesse az alábbi lépéseket a saját létrehozásához.

Előfeltételek

A Microsoft Entra ID előfeltételei

A Microsoft Entra-azonosítóval javasolt kulcs nélküli hitelesítéshez a következőket kell elvégeznie:

Erőforrásadatok lekérése

Az alkalmazás Azure AI-Search szolgáltatás történő hitelesítéséhez le kell kérnie a következő adatokat:

Változó neve Érték
SEARCH_API_ENDPOINT Ez az érték az Azure Portalon található. Válassza ki a keresési szolgáltatást, majd a bal oldali menüben válassza az Áttekintés lehetőséget. Az Essentials alatt található URL-érték a szükséges végpont. A végpontok például a következőképpen nézhetnek ki: https://mydemo.search.windows.net.

További információ a kulcs nélküli hitelesítésről és a környezeti változók beállításáról.

Beállítás

  1. Hozzon létre egy új mappát full-text-quickstart , amely tartalmazza az alkalmazást, és nyissa meg a Visual Studio Code-ot abban a mappában a következő paranccsal:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Hozza létre a package.json következő paranccsal:

    npm init -y
    
  3. Frissítse az package.json ECMAScriptet a következő paranccsal:

    npm pkg set type=module
    
  4. Telepítse az Azure AI Search ügyfélkódtárát (Azure.Search.Documents) JavaScripthez a következőkkel:

    npm install @azure/search-documents
    
  5. Az ajánlott jelszó nélküli hitelesítéshez telepítse az Azure Identity ügyfélkódtárat a következőkkel:

    npm install @azure/identity
    

Keresési index létrehozása, betöltése és lekérdezése

Az előző beállítási szakaszban telepítette az Azure AI Search ügyfélkódtárat és más függőségeket.

Ebben a szakaszban kódot ad hozzá egy keresési index létrehozásához, dokumentumokkal való betöltéséhez és lekérdezések futtatásához. Futtassa a programot az eredmények megtekintéséhez a konzolon. A kód részletes magyarázatát a kódszakaszban találja.

A rövid útmutatóban szereplő mintakód a Microsoft Entra-azonosítót használja az ajánlott kulcs nélküli hitelesítéshez. Ha inkább API-kulcsot szeretne használni, lecserélheti az DefaultAzureCredential objektumot egy objektumra AzureKeyCredential .

const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
  1. Hozzon létre egy index.ts nevű új fájlt, és illessze be a következő kódot a index.ts:

    // 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": "Description_fr",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": false,
    			"sortable": false,
    			"facetable": false,
    			"analyzerName": "fr.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 cliff", 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. Hozzon létre egy hotels.json nevű fájlt, és illessze be a következő kódot hotels.json:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Secret Point Motel",
                "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                "Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
                "Category": "Boutique",
                "Tags": ["pool", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "1970-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "HotelId": "2",
                "HotelName": "Twin Dome Motel",
                "Description": "The hotel is situated in a  nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
                "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "1979-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Triple Landscape Hotel",
                "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.",
                "Category": "Resort and Spa",
                "Tags": ["air conditioning", "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 Cliff Hotel",
                "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
                "Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "24-hour front desk service"],
                "ParkingIncluded": true,
                "LastRenovationDate": "1960-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. Hozza létre a fájlt a tsconfig.json TypeScript-kód fordításához, és másolja a következő kódot az ECMAScripthez.

    {
        "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. Transpile TypeScriptről JavaScriptre.

    tsc
    
  5. Jelentkezzen be az Azure-ba a következő paranccsal:

    az login
    
  6. Futtassa a JavaScript-kódot a következő paranccsal:

    node index.js
    

A kód ismertetése

Index létrehozása

Hozzon létre egy fájl hotels_quickstart_index.json. Ez a fájl határozza meg, hogyan működik az Azure AI Search a következő lépésben betöltődő dokumentumokkal. Az egyes mezőket egy name adott mező azonosítja, és rendelkezik egy megadott typemezővel. Minden mező indexattribútumok sorozatával is rendelkezik, amelyek meghatározzák, hogy az Azure AI Search képes-e keresni, szűrni, rendezni és kezelni a mezőt. A mezők többsége egyszerű adattípus, de néhány olyan összetett típus, amely AddressType lehetővé teszi, hogy gazdag adatstruktúrákat hozzon létre az indexben. A támogatott adattípusokról és indexattribútumokról az Index létrehozása (REST) című témakörben olvashat bővebben.

Importálni szeretnénk hotels_quickstart_index.json, hogy a fő függvény hozzáférhessen az indexdefinícióhoz.

import indexDefinition from './hotels_quickstart_index.json';

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

A fő függvényen belül létrehozunk egy SearchIndexClient, az Azure AI Search indexeinek létrehozására és kezelésére szolgáló parancsot.

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

Ezután törölni szeretnénk az indexet, ha már létezik. Ez a művelet a tesztelési/demókódok gyakori gyakorlata.

Ehhez definiálunk egy egyszerű függvényt, amely megpróbálja törölni az indexet.

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

A függvény futtatásához kinyerjük az index nevét az indexdefinícióból, és átadjuk a indexName függvénynekdeleteIndexIfExists().indexClient

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

Ezután készen állunk az index metódussal való létrehozására createIndex() .

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

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

Dokumentumok betöltése

Az Azure AI Searchben a dokumentumok olyan adatstruktúrák, amelyek egyaránt bemenetek az indexeléshez és a lekérdezésekből származó kimenetekhez. Ezeket az adatokat leküldheti az indexbe, vagy használhat indexelőt. Ebben az esetben programozott módon leküldjük a dokumentumokat az indexbe.

A dokumentumbemenetek lehetnek egy adatbázis sorai, blobok a Blob Storage-ban, vagy a mintában szereplő JSON-dokumentumok a lemezen. Letöltheti hotels.json , vagy létrehozhat saját hotels.json fájlt a következő tartalommal:

Az indexDefinitionhez hasonlóan a index.ts tetején is importálnunk hotels.json kell, hogy az adatok elérhetők legyenek a fő függvényünkben.

import hotelData from './hotels.json';

interface Hotel {
    HotelId: string;
    HotelName: string;
    Description: string;
    Description_fr: 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"];

Ha adatokat szeretne indexelni a keresési indexbe, létre kell hoznunk egy SearchClient. Bár az SearchIndexClient indexek létrehozására és kezelésére szolgál, a SearchClient dokumentumok feltöltésére és az index lekérdezésére szolgál.

Kétféleképpen hozhat létre .SearchClient Az első lehetőség a nulláról történő létrehozás SearchClient :

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

Másik lehetőségként a getSearchClient() következő metódus SearchIndexClient használatával is létrehozhatja a következőt SearchClient:

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

Az ügyfél definiálása után töltse fel a dokumentumokat a keresési indexbe. Ebben az esetben a metódust mergeOrUploadDocuments() használjuk, amely feltölti a dokumentumokat, vagy egyesíti őket egy meglévő dokumentummal, ha már létezik ugyanazzal a kulccsal rendelkező dokumentum. Ezután ellenőrizze, hogy a művelet sikeres volt-e, mert legalább az első dokumentum létezik.

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

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

Futtassa újra a programot a következővel tsc && node index.ts: . Az 1. lépésben látottaktól kissé eltérő üzenetkészletnek kell megjelennie. Ezúttal az index létezik , és látnia kell egy, a törlésről szóló üzenetet, mielőtt az alkalmazás létrehozza az új indexet, és közzétennénk az adatokat.

Mielőtt a következő lépésben futtatnánk a lekérdezéseket, definiáljon egy függvényt, hogy a program egy másodpercig várakozzon. Ez csak tesztelési/demó céljából történik, hogy az indexelés befejeződjön, és hogy a dokumentumok elérhetők legyenek az indexben a lekérdezéseinkhez.

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

Ha azt szeretné, hogy a program egy másodpercig várjon, hívja meg a függvényt sleep :

sleep(1000);

Keresés az indexekben

Egy index létrehozásával és a feltöltött dokumentumokkal lekérdezéseket küldhet az indexnek. Ebben a szakaszban öt különböző lekérdezést küldünk a keresési indexbe, hogy bemutassuk az Ön számára elérhető különböző lekérdezési funkciókat.

A lekérdezések egy sendQueries() függvényben vannak megírva, amelyet a fő függvényben hívunk meg az alábbiak szerint:

await sendQueries(searchClient);

A rendszer a lekérdezéseket a search() következő módszerrel küldi searchClientel: . Az első paraméter a keresési szöveg, a második pedig a keresési beállításokat adja meg.

1. lekérdezési példa

Az első lekérdezés minden *kereséssel egyenértékű, és az index három mezőjét választja ki. Ajánlott csak a szükséges mezőket használni select , mert a szükségtelen adatok visszakérése késést okozhat a lekérdezésekben.

Ennek searchOptions a lekérdezésnek a értéke is be van includeTotalCount állítva true, amely a talált találatok számát adja vissza.

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
}

Az alább ismertetett többi lekérdezést is hozzá kell adni a sendQueries() függvényhez. Itt külön vannak elválasztva az olvashatóság érdekében.

2. lekérdezési példa

A következő lekérdezésben megadjuk a keresési kifejezést "wifi" , és egy szűrőt is belefoglalunk, amely csak olyan eredményeket ad vissza, ahol az állapot egyenlő 'FL'. Az eredményeket a szálloda is rendezi 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)}`);
}

3. lekérdezési példa

Ezután a keresés egyetlen kereshető mezőre korlátozódik a searchFields paraméter használatával. Ez a megközelítés nagyszerű lehetőség arra, hogy hatékonyabbá tegye a lekérdezést, ha tudja, hogy csak bizonyos mezőkben lévő egyezések érdeklik.

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

4. lekérdezési példa

Egy másik gyakori lehetőség a lekérdezésbe való belefoglalás.facets Az aspektusok lehetővé teszik, hogy ön által irányított részletezéseket biztosítson a felhasználói felületen található eredményekből. Az eredmények az eredménypanelen jelölőnégyzetekké alakíthatók.

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

5. lekérdezési példa

A végső lekérdezés a getDocument()searchClient. Így hatékonyan lekérhet egy dokumentumot a kulcsával.

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

Lekérdezések összegzése

Az előző lekérdezések több módon is egyeztetik a kifejezéseket a lekérdezésekben: teljes szöveges keresés, szűrők és automatikus kiegészítés.

A metódussal searchClient.search teljes szöveges keresést és szűrőket hajtunk végre. A keresési lekérdezések átadhatók a sztringben searchText , míg egy szűrőkifejezés átadható az filterSearchOptions osztály tulajdonságában. Keresés nélküli szűréshez egyszerűen adja meg a "*" értéket a searchTextsearch metódus paraméteréhez. Ha szűrés nélkül szeretne keresni, hagyja meg a filter tulajdonságot, vagy egyáltalán ne adja át a példányt SearchOptions .

Erőforrások törlése

Ha a saját előfizetésében dolgozik, érdemes az egyes projektek végén eldöntenie, hogy szüksége lesz-e még a létrehozott erőforrásokra. A továbbra is futó erőforrások költségekkel járhatnak. Az erőforrásokat törölheti egyesével, vagy az erőforráscsoport törlésével eltávolíthatja a benne lévő összes erőforrást is.

Az erőforrásokat az Azure Portalon, a bal oldali navigációs panel Minden erőforrás vagy erőforráscsoport hivatkozásával keresheti meg és kezelheti.

Ha ingyenes szolgáltatást használ, ne feledje, hogy három indexre, indexelőre és adatforrásra korlátozódik. Az Azure Portalon törölheti az egyes elemeket, hogy a korlát alatt maradjon.

Következő lépés

Ebben a rövid útmutatóban feladatokat dolgozott ki egy index létrehozásához, dokumentumokba való betöltéséhez és lekérdezések futtatásához. Különböző szakaszokban billentyűparancsokkal egyszerűsítettük a kódot az olvashatóság és a megértés érdekében. Most, hogy megismerte az alapfogalmakat, próbáljon ki egy oktatóanyagot, amely meghívja az Azure AI Search API-kat egy webalkalmazásban.