Dela via


Snabbstart: Fulltextsökning med hjälp av Azure SDK:er

Lär dig hur du använder klientbiblioteket Azure.Search.Documents för att skapa, läsa in och köra frågor mot ett sökindex med hjälp av exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor samt en BM25-rangordningsalgoritm för bedömning av resultat.

Den här snabbstarten skapar och frågar ett litet hotell-snabbstartsindex som innehåller data om fyra hotell.

Dricks

Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.

Förutsättningar

  • En aktiv Azure-prenumeration – Skapa en kostnadsfritt
  • En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. Du kan använda en kostnadsfri nivå för den här snabbstarten.

Krav för Microsoft Entra-ID

För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:

  • Installera Azure CLI som används för nyckellös autentisering med Microsoft Entra-ID.
  • Tilldela både rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.

Hämta resursinformation

Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:

Variabelnamn Värde
SEARCH_API_ENDPOINT Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn. Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

Läs mer om nyckellös autentisering och inställning av miljövariabler.

Konfigurera

  1. Skapa en ny mapp full-text-quickstart som ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Skapa ett nytt konsolprogram med följande kommando:

    dotnet new console
    
  3. Installera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för .NET med:

    dotnet add package Azure.Search.Documents
    
  4. För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID installerar du Azure.Identity-paketet med:

    dotnet add package Azure.Identity
    
  5. För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID loggar du in på Azure med följande kommando:

    az login
    

Skapa, läsa in och fråga ett sökindex

I föregående konfigurationsavsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket.

I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
  1. I Program.cs klistrar du in följande kod. Redigera variablerna serviceName och apiKey med söktjänstens namn och administratörs-API-nyckel.

    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. I samma mapp skapar du en ny fil med namnet Hotel.cs och klistrar in följande kod. Den här koden definierar strukturen för ett hotelldokument.

    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. Skapa en ny fil med namnet Hotel.cs och klistra in följande kod för att definiera strukturen för ett hotelldokument. Attribut i fältet avgör hur det används i ett program. Attributet måste till exempel IsFilterable tilldelas till varje fält som stöder ett filteruttryck.

    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. Skapa en ny fil med namnet Address.cs och klistra in följande kod för att definiera strukturen för ett adressdokument.

    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. Skapa en ny fil med namnet Hotel.Methods.cs och klistra in följande kod för att definiera en ToString() åsidosättning för Hotel klassen.

    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. Skapa en ny fil med namnet Address.Methods.cs och klistra in följande kod för att definiera en ToString() åsidosättning för Address klassen.

    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. Skapa och kör programmet med följande kommando:

    dotnet run
    

Utdata innehåller meddelanden från Console.WriteLine, med tillägg av frågeinformation och resultat.

Förklara koden

I föregående avsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket. Du har lagt till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du körde programmet för att se resultatet i konsolen.

I det här avsnittet förklarar vi koden som du lade till i konsolprogrammet.

Skapa en sökklient

I Program.cs skapade du två klienter:

Båda klienterna behöver slutpunkten för söktjänsten och autentiseringsuppgifterna som beskrevs tidigare i avsnittet resursinformation .

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

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

Skapa ett index

Den här snabbstarten skapar ett Hotell-index som du läser in med hotelldata och kör frågor mot. I det här steget definierar du fälten i indexet. Varje fältdefinition innehåller ett namn, en datatyp och attribut som avgör hur fältet används.

I det här exemplet används synkrona metoder i biblioteket Azure.Search.Documents för enkelhet och läsbarhet. För produktionsscenarier bör du dock använda asynkrona metoder för att hålla appen skalbar och dynamisk. Du skulle till exempel använda CreateIndexAsync i stället för CreateIndex.

Definiera strukturerna

Du skapade två hjälpklasser, Hotel.cs och Address.cs, för att definiera strukturen för ett hotelldokument och dess adress. Klassen Hotel innehåller fält för ett hotell-ID, namn, beskrivning, kategori, taggar, parkering, renoveringsdatum, betyg och adress. Klassen Address innehåller fält för gatuadress, ort, delstat/provins, postnummer och land/region.

I azure.search.documents-klientbiblioteket kan du använda SearchableField och SimpleField för att effektivisera fältdefinitioner. Båda är derivat av ett SearchField och kan förenkla koden:

  • SimpleField kan vara vilken datatyp som helst, är alltid inte sökbar (ignoreras för fulltextsökningsfrågor) och kan hämtas (inte dold). Andra attribut är inaktiverade som standard, men kan aktiveras. Du kan använda ett SimpleField för dokument-ID eller fält som endast används i filter, fasetter eller bedömningsprofiler. I så fall bör du tillämpa eventuella attribut som är nödvändiga för scenariot, till exempel IsKey = true för ett dokument-ID. Mer information finns i SimpleFieldAttribute.cs i källkoden.

  • SearchableField måste vara en sträng och är alltid sökbar och hämtningsbar. Andra attribut är inaktiverade som standard, men kan aktiveras. Eftersom den här fälttypen är sökbar stöder den synonymer och det fullständiga komplementet av analysverktygsegenskaper. Mer information finns i SearchableFieldAttribute.cs i källkoden.

Oavsett om du använder det grundläggande SearchField API:et eller någon av hjälpmodellerna måste du uttryckligen aktivera attribut för filter, fasetter och sortering. Till exempel måste IsFilterable, IsSortable och IsFacetable uttryckligen tillskrivas, som du ser i föregående exempel.

Skapa sökindexet

I Program.cs skapar du ett SearchIndex-objekt och anropar sedan metoden CreateIndex för att uttrycka indexet i söktjänsten. Indexet innehåller också en SearchSuggester för att aktivera automatisk komplettering i de angivna fälten.

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

Läsa in dokument

Azure AI Search söker efter innehåll som lagras i tjänsten. I det här steget läser du in JSON-dokument som överensstämmer med hotellindexet du skapade.

I Azure AI Search är sökdokument datastrukturer som både är indata för indexering och utdata från frågor. Som hämtats från en extern datakälla kan dokumentindata vara rader i en databas, blobar i Blob Storage eller JSON-dokument på disk. I det här exemplet tar vi en genväg och bäddar in JSON-dokument för fyra hotell i själva koden.

När du laddar upp dokument måste du använda ett IndexDocumentsBatch-objekt . Ett IndexDocumentsBatch objekt innehåller en samling åtgärder, som var och en innehåller ett dokument och en egenskap som talar om för Azure AI Search vilken åtgärd som ska utföras (ladda upp, slå samman, ta bort och slå sammanEllerUpload).

I Program.cs skapar du en matris med dokument och indexåtgärder och skickar sedan matrisen till IndexDocumentsBatch. Följande dokument överensstämmer med indexet hotels-quickstart enligt definitionen i hotellklassen.

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

När du har initierat Objektet IndexDocumentsBatch kan du skicka det till indexet genom att anropa IndexDocuments på ditt SearchClient-objekt .

Du läser in dokument med SearchClient i Main(), men åtgärden kräver även administratörsbehörighet för tjänsten, som vanligtvis är associerad med SearchIndexClient. Ett sätt att konfigurera den här åtgärden är att hämta SearchClient genom SearchIndexClient (searchIndexClient i det här exemplet).

SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);

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

Eftersom vi har en konsolapp som kör alla kommandon sekventiellt lägger vi till en väntetid på 2 sekunder mellan indexering och frågor.

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

Fördröjningen på 2 sekunder kompenserar för indexering, vilket är asynkront, så att alla dokument kan indexeras innan frågorna körs. Kodning i en fördröjning är vanligtvis bara nödvändigt i demonstrationer, tester och exempelprogram.

Sök i ett index

Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.

Det här avsnittet lägger till två funktioner: frågelogik och resultat. För frågor använder du sökmetoden . Den här metoden tar söktext (frågesträngen) och andra alternativ.

Klassen SearchResults representerar resultatet.

I Program.csWriteDocuments skriver metoden ut sökresultat till konsolen.

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

Frågeexempel 1

Metoden RunQueries kör frågor och returnerar resultat. Resultatet är Hotellobjekt. Det här exemplet visar metodsignaturen och den första frågan. Den här frågan visar parametern Select som gör att du kan skapa resultatet med hjälp av valda fält från dokumentet.

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

Frågeexempel 2

I den andra frågan söker du efter en term, lägger till ett filter som väljer dokument där Omdöme är större än 4 och sorterar sedan efter Klassificering i fallande ordning. Filter är ett booleskt uttryck som utvärderas över IsFilterable-fält i ett index. Filtrera frågor antingen inkludera eller exkludera värden. Därför finns det ingen relevanspoäng associerad med en filterfråga.

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

Frågeexempel 3

Den tredje frågan visar searchFields, som används för att begränsa en fulltextsökningsåtgärd till specifika fält.

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

Frågeexempel 4

Den fjärde frågan visar facets, som kan användas för att strukturera en fasetterad navigeringsstruktur.

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

Frågeexempel 5

I den femte frågan returnerar du ett specifikt dokument. Ett dokumentuppslag är ett typiskt svar på OnClick händelsen i en resultatuppsättning.

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

Frågeexempel 6

Den sista frågan visar syntaxen för automatisk komplettering, som simulerar en partiell användarinmatning av sa som matchar två möjliga matchningar i de sourceFields som är associerade med den förslagsanvändare som du definierade i indexet.

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

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

Sammanfattning av frågor

Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.

Fulltextsökning och -filter utförs med metoden SearchClient.Search . En sökfråga kan skickas i strängensearchText, medan ett filteruttryck kan skickas i filteregenskapen för klassen SearchOptions. Om du vill filtrera utan att söka skickar du "*" bara efter parametern searchTextför sökmetoden . Om du vill söka utan filtrering lämnar du Filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.

Lär dig hur du använder klientbiblioteket Azure.Search.Documents för att skapa, läsa in och köra frågor mot ett sökindex med hjälp av exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor samt en BM25-rangordningsalgoritm för bedömning av resultat.

Den här snabbstarten skapar och frågar ett litet hotell-snabbstartsindex som innehåller data om fyra hotell.

Dricks

Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.

Förutsättningar

  • En aktiv Azure-prenumeration – Skapa en kostnadsfritt
  • En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. Du kan använda en kostnadsfri nivå för den här snabbstarten.

Krav för Microsoft Entra-ID

För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:

  • Installera Azure CLI som används för nyckellös autentisering med Microsoft Entra-ID.
  • Tilldela både rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.

Hämta resursinformation

Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:

Variabelnamn Värde
SEARCH_API_ENDPOINT Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn. Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

Läs mer om nyckellös autentisering och inställning av miljövariabler.

Konfigurera

Exemplet i den här snabbstarten fungerar med Java Runtime. Installera ett Java Development Kit, till exempel Azul Zulu OpenJDK. Microsoft Build of OpenJDK eller din önskade JDK bör också fungera.

  1. Installera Apache Maven. Kör mvn -v sedan för att bekräfta att installationen har slutförts.

  2. Skapa en ny pom.xml fil i roten av projektet och kopiera följande kod till den:

    <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. Installera beroendena, inklusive Azure AI Search-klientbiblioteket (Azure.Search.Documents) för Java- och Azure Identity-klientbiblioteket för Java med:

    mvn clean dependency:copy-dependencies
    
  4. För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID loggar du in på Azure med följande kommando:

    az login
    

Skapa, läsa in och fråga ett sökindex

I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.

I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Skapa en ny fil med namnet App.java och klistra in följande kod i 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. Skapa en ny fil med namnet Hotel.java och klistra in följande kod i 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. Skapa en ny fil med namnet Address.java och klistra in följande kod i 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. Kör det nya konsolprogrammet:

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

Förklara koden

I föregående avsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket. Du har lagt till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du körde programmet för att se resultatet i konsolen.

I det här avsnittet förklarar vi koden som du lade till i konsolprogrammet.

Skapa en sökklient

I App.java skapade du två klienter:

  • SearchIndexClient skapar indexet.
  • SearchClient läser in och frågar ett befintligt index.

Båda klienterna behöver slutpunkten för söktjänsten och autentiseringsuppgifterna som beskrevs tidigare i avsnittet resursinformation.

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

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

Skapa ett index

Den här snabbstarten skapar ett Hotell-index som du läser in med hotelldata och kör frågor mot. I det här steget definierar du fälten i indexet. Varje fältdefinition innehåller ett namn, en datatyp och attribut som avgör hur fältet används.

I det här exemplet används synkrona metoder i biblioteket Azure.Search.Documents för enkelhet och läsbarhet. För produktionsscenarier bör du dock använda asynkrona metoder för att hålla appen skalbar och dynamisk. Du skulle till exempel använda CreateIndexAsync i stället för CreateIndex.

Definiera strukturerna

Du skapade två hjälpklasser, Hotel.java och Address.java, för att definiera strukturen för ett hotelldokument och dess adress. Hotellklassen innehåller fält för ett hotell-ID, namn, beskrivning, kategori, taggar, parkering, renoveringsdatum, betyg och adress. Klassen Address innehåller fält för gatuadress, ort, delstat/provins, postnummer och land/region.

I azure.search.documents-klientbiblioteket kan du använda SearchableField och SimpleField för att effektivisera fältdefinitioner.

  • SimpleField kan vara vilken datatyp som helst, är alltid inte sökbar (ignoreras för fulltextsökningsfrågor) och kan hämtas (inte dold). Andra attribut är inaktiverade som standard, men kan aktiveras. Du kan använda simplefield för dokument-ID:er eller fält som endast används i filter, fasetter eller bedömningsprofiler. I så fall måste du tillämpa eventuella attribut som är nödvändiga för scenariot, till exempel IsKey = true för ett dokument-ID.
  • SearchableField måste vara en sträng och är alltid sökbar och hämtningsbar. Andra attribut är inaktiverade som standard, men kan aktiveras. Eftersom den här fälttypen är sökbar stöder den synonymer och det fullständiga komplementet av analysverktygsegenskaper.

Oavsett om du använder det grundläggande SearchField API:et eller någon av hjälpmodellerna måste du uttryckligen aktivera attribut för filter, fasetter och sortering. Till exempel isFilterable, isSortable, och isFacetable måste uttryckligen tillskrivas, som du ser i föregående exempel.

Skapa sökindexet

I App.javaskapar du ett SearchIndex objekt i main metoden och anropar createOrUpdateIndex sedan metoden för att skapa indexet i söktjänsten. Indexet innehåller även en SearchSuggester för att aktivera automatisk komplettering på de angivna fälten.

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

Läsa in dokument

Azure AI Search söker efter innehåll som lagras i tjänsten. I det här steget läser du in JSON-dokument som överensstämmer med hotellindexet du skapade.

I Azure AI Search är sökdokument datastrukturer som både är indata för indexering och utdata från frågor. Som hämtats från en extern datakälla kan dokumentindata vara rader i en databas, blobar i Blob Storage eller JSON-dokument på disk. I det här exemplet tar vi en genväg och bäddar in JSON-dokument för fyra hotell i själva koden.

När du laddar upp dokument måste du använda ett IndexDocumentsBatch-objekt . Ett IndexDocumentsBatch objekt innehåller en samling IndexActions, som var och en innehåller ett dokument och en egenskap som talar om för Azure AI Search vilken åtgärd som ska utföras (ladda upp, slå samman, ta bort och mergeOrUpload).

I App.javaskapar du dokument och indexåtgärder och skickar dem sedan till IndexDocumentsBatch. Följande dokument överensstämmer med indexet hotels-quickstart enligt definitionen i hotellklassen.

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

När du har initierat IndexDocumentsBatch objektet kan du skicka det till indexet genom att anropa indexDocuments för objektet SearchClient .

Du läser in dokument med SearchClient i main(), men åtgärden kräver även administratörsbehörighet för tjänsten, som vanligtvis är associerad med SearchIndexClient. Ett sätt att konfigurera den här åtgärden är att hämta SearchClient genom SearchIndexClient (searchIndexClient i det här exemplet).

uploadDocuments(searchClient);

Eftersom vi har en konsolapp som kör alla kommandon sekventiellt lägger vi till en väntetid på 2 sekunder mellan indexering och frågor.

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

Fördröjningen på 2 sekunder kompenserar för indexering, vilket är asynkront, så att alla dokument kan indexeras innan frågorna körs. Kodning i en fördröjning är vanligtvis bara nödvändigt i demonstrationer, tester och exempelprogram.

Sök i ett index

Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.

Det här avsnittet lägger till två funktioner: frågelogik och resultat. För frågor använder du sökmetoden. Den här metoden tar söktext (frågesträngen) och andra alternativ.

WriteDocuments I App.javaskriver metoden ut sökresultat till konsolen.

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

Frågeexempel 1

Metoden RunQueries kör frågor och returnerar resultat. Resultatet är Hotellobjekt. Det här exemplet visar metodsignaturen och den första frågan. Den här frågan visar parametern Select som gör att du kan skapa resultatet med hjälp av valda fält från dokumentet.

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

Frågeexempel 2

I den andra frågan söker du efter en term, lägger till ett filter som väljer dokument där Omdöme är större än 4 och sorterar sedan efter Klassificering i fallande ordning. Filter är ett booleskt uttryck som utvärderas över isFilterable fält i ett index. Filtrera frågor antingen inkludera eller exkludera värden. Därför finns det ingen relevanspoäng associerad med en filterfråga.

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

Frågeexempel 3

Den tredje frågan visar searchFields, som används för att begränsa en fulltextsökningsåtgärd till specifika fält.

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

Frågeexempel 4

Den fjärde frågan visar facets, som kan användas för att strukturera en fasetterad navigeringsstruktur.

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

Frågeexempel 5

I den femte frågan returnerar du ett specifikt dokument.

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

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

Frågeexempel 6

Den sista frågan visar syntaxen för automatisk komplettering, vilket simulerar en partiell användarinmatning av s som matchar två möjliga matchningar i den sourceFields associerade med den förslagsanvändare som du definierade i indexet.

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

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

Sammanfattning av frågor

Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.

Fulltextsökning och -filter utförs med metoden SearchClient.search . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter egenskapen för klassen SearchOptions . Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.

Lär dig hur du använder klientbiblioteket Azure.Search.Documents för att skapa, läsa in och köra frågor mot ett sökindex med hjälp av exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor samt en BM25-rangordningsalgoritm för bedömning av resultat.

Den här snabbstarten skapar och frågar ett litet hotell-snabbstartsindex som innehåller data om fyra hotell.

Dricks

Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.

Förutsättningar

  • En aktiv Azure-prenumeration – Skapa en kostnadsfritt
  • En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. Du kan använda en kostnadsfri nivå för den här snabbstarten.

Krav för Microsoft Entra-ID

För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:

  • Installera Azure CLI som används för nyckellös autentisering med Microsoft Entra-ID.
  • Tilldela både rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.

Hämta resursinformation

Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:

Variabelnamn Värde
SEARCH_API_ENDPOINT Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn. Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

Läs mer om nyckellös autentisering och inställning av miljövariabler.

Konfigurera

  1. Skapa en ny mapp full-text-quickstart som ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. package.json Skapa med följande kommando:

    npm init -y
    
  3. Installera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för JavaScript med:

    npm install @azure/search-documents
    
  4. För den rekommenderade lösenordslösa autentiseringen installerar du Azure Identity-klientbiblioteket med:

    npm install @azure/identity
    

Skapa, läsa in och fråga ett sökindex

I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.

I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Skapa en ny fil med namnet index.js och klistra in följande kod i 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. Skapa en fil med namnet hotels.json och klistra in följande kod i 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. Skapa en fil med namnet hotels_quickstart_index.json och klistra in följande kod i 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. Logga in på Azure med följande kommando:

    az login
    
  5. Kör JavaScript-koden med följande kommando:

    node index.js
    

Förklara koden

Skapa index

Filen hotels_quickstart_index.json definierar hur Azure AI Search fungerar med de dokument som du läser in i nästa steg. Varje fält identifieras av en name och har en angiven type. Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).

Med vår indexdefinition på plats vill vi importera hotels_quickstart_index.json överst i index.js så att huvudfunktionen kan komma åt indexdefinitionen.

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

I huvudfunktionen skapar vi sedan en SearchIndexClient, som används för att skapa och hantera index för Azure AI Search.

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

Sedan vill vi ta bort indexet om det redan finns. Den här åtgärden är en vanlig metod för test-/demokod.

Det gör vi genom att definiera en enkel funktion som försöker ta bort indexet.

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

För att köra funktionen extraherar vi indexnamnet från indexdefinitionen och skickar indexName med indexClient till deleteIndexIfExists() funktionen.

const indexName = indexDefinition["name"];

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

Efter det är vi redo att skapa indexet med createIndex() -metoden.

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

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

Läsa in dokument

I Azure AI Search är dokument datastrukturer som både är indata för indexering och utdata från frågor. Du kan skicka sådana data till indexet eller använda en indexerare. I det här fallet skickar vi programmatiskt dokumenten till indexet.

Dokumentindata kan vara rader i en databas, blobar i Blob Storage eller, som i det här exemplet, JSON-dokument på disk. På samma sätt som vi gjorde med indexDefinitionmåste vi också importera hotels.json överst i index.js så att data kan nås i vår huvudfunktion.

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

För att indexera data i sökindexet måste vi nu skapa en SearchClient. SearchIndexClient Används för att skapa och hantera ett index, SearchClient men används för att ladda upp dokument och köra frågor mot indexet.

Det finns två sätt att skapa en SearchClient. Det första alternativet är att skapa en SearchClient från grunden:

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

Du kan också använda getSearchClient() metoden SearchIndexClient för för att skapa SearchClient:

const searchClient = indexClient.getSearchClient(indexName);

Nu när klienten har definierats laddar du upp dokumenten till sökindexet. I det här fallet använder mergeOrUploadDocuments() vi metoden som laddar upp dokumenten eller sammanfogar dem med ett befintligt dokument om det redan finns ett dokument med samma nyckel.

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

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

Sök i ett index

När ett index har skapats och dokument har laddats upp är du redo att skicka frågor till indexet. I det här avsnittet skickar vi fem olika frågor till sökindexet för att demonstrera olika frågefunktioner som är tillgängliga för dig.

Frågorna skrivs i en sendQueries() funktion som vi anropar i huvudfunktionen enligt följande:

await sendQueries(searchClient);

Frågor skickas med metoden search()searchClient. Den första parametern är söktexten och den andra parametern anger sökalternativ.

Frågeexempel 1

Den första frågan söker efter *, vilket motsvarar att söka efter allt och väljer tre av fälten i indexet. Det är en bra idé att bara select använda de fält du behöver eftersom onödiga data kan ge svarstid till dina frågor.

För searchOptions den här frågan har includeTotalCount också angetts till true, som returnerar antalet matchande resultat som hittades.

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
}

De återstående frågorna som beskrivs nedan bör också läggas till i sendQueries() funktionen. De är separerade här för läsbarhet.

Frågeexempel 2

I nästa fråga anger vi söktermen "wifi" och inkluderar även ett filter för att endast returnera resultat där tillståndet är lika med 'FL'. Resultaten beställs också av hotellets 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)}`);
}

Frågeexempel 3

Därefter begränsas sökningen till ett enda sökbart fält med hjälp av parametern searchFields . Den här metoden är ett bra alternativ för att göra frågan mer effektiv om du vet att du bara är intresserad av matchningar i vissa fält.

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

Frågeexempel 4

Ett annat vanligt alternativ att ta med i en fråga är facets. Med fasetter kan du skapa filter i användargränssnittet för att göra det enkelt för användarna att veta vilka värden de kan filtrera ned till.

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

Frågeexempel 5

Den sista frågan använder getDocument() metoden för searchClient. På så sätt kan du effektivt hämta ett dokument med dess nyckel.

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

Sammanfattning av frågor

Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.

Fulltextsökning och -filter utförs med hjälp av searchClient.search metoden . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter klassens SearchOptions egenskap. Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.

Lär dig hur du använder klientbiblioteket Azure.Search.Documents för att skapa, läsa in och köra frågor mot ett sökindex med hjälp av exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor samt en BM25-rangordningsalgoritm för bedömning av resultat.

Den här snabbstarten skapar och frågar ett litet hotell-snabbstartsindex som innehåller data om fyra hotell.

Dricks

Du kan ladda ned och köra en färdig notebook-fil.

Förutsättningar

  • En aktiv Azure-prenumeration – Skapa en kostnadsfritt
  • En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. Du kan använda en kostnadsfri nivå för den här snabbstarten.
  • Visual Studio Code med Python-tillägget eller motsvarande IDE med Python 3.10 eller senare. Om du inte har en lämplig version av Python installerad kan du följa anvisningarna i VS Code Python-självstudien.

Krav för Microsoft Entra-ID

För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:

  • Installera Azure CLI som används för nyckellös autentisering med Microsoft Entra-ID.
  • Tilldela både rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.

Hämta resursinformation

Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:

Variabelnamn Värde
SEARCH_API_ENDPOINT Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn. Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

Läs mer om nyckellös autentisering och inställning av miljövariabler.

Konfigurera din miljö

Du kör exempelkoden i en Jupyter-anteckningsbok. Därför måste du konfigurera din miljö för att köra Jupyter Notebooks.

  1. Ladda ned eller kopiera exempelanteckningsboken från GitHub.

  2. Öppna anteckningsboken i Visual Studio Code.

  3. Skapa en ny Python-miljö som ska användas för att installera de paket du behöver för den här självstudien.

    Viktigt!

    Installera inte paket i din globala Python-installation. Du bör alltid använda en virtuell miljö eller conda-miljö när du installerar Python-paket, annars kan du avbryta din globala installation av Python.

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

    Det kan ta en minut att konfigurera. Om du stöter på problem kan du läsa Python-miljöer i VS Code.

  4. Installera Jupyter Notebooks och IPython Kernel for Jupyter Notebooks om du inte redan har dem.

    pip install jupyter
    pip install ipykernel
    python -m ipykernel install --user --name=.venv
    
  5. Välj notebook-kerneln.

    1. I det övre högra hörnet i notebook-filen väljer du Välj kernel.
    2. Om du ser .venv i listan väljer du den. Om du inte ser den väljer du Välj en annan Kernel>Python-miljö.>.venv

Skapa, läsa in och fråga ett sökindex

I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .

  1. Kontrollera att anteckningsboken är öppen i kerneln .venv enligt beskrivningen i föregående avsnitt.

  2. Kör den första kodcellen för att installera de paket som krävs, inklusive azure-search-documents.

    ! pip install azure-search-documents==11.6.0b1 --quiet
    ! pip install azure-identity --quiet
    ! pip install python-dotenv --quiet
    
  3. Ersätt innehållet i den andra kodcellen med följande kod beroende på din autentiseringsmetod.

    Kommentar

    Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

    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. Ta bort följande två rader från cellen Skapa en indexkod . Autentiseringsuppgifterna har redan angetts i den tidigare kodcellen.

    from azure.core.credentials import AzureKeyCredential
    credential = AzureKeyCredential(search_api_key)
    
  5. Kör cellen Skapa en indexkod för att skapa ett sökindex.

  6. Kör de återstående kodcellerna sekventiellt för att läsa in dokument och köra frågor.

Förklara koden

Skapa ett index

SearchIndexClient används för att skapa och hantera index för Azure AI Search. Varje fält identifieras av en name och har en angiven type.

Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).

Skapa en dokumentnyttolast och ladda upp dokument

Använd en indexåtgärd för åtgärdstypen, till exempel uppladdning eller sammanslagning och uppladdning. Dokument kommer från Exemplet HotelsData på GitHub.

Sök i ett index

Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.

Använd sökmetoden för klassen search.client.

Exempelfrågorna i notebook-filen är:

  • Grundläggande fråga: Kör en tom sökning (search=*), som returnerar en orankad lista (sökpoäng = 1,0) godtyckliga dokument. Eftersom det inte finns några kriterier inkluderas alla dokument i resultatet.
  • Termfråga: Lägger till hela termer i sökuttrycket ("wifi"). Den här frågan anger att resultaten endast innehåller de fälten i -instruktionen select . Om du begränsar fälten som kommer tillbaka minimeras mängden data som skickas tillbaka över tråden och minskar sökfördröjningen.
  • Filtrerad fråga: Lägg till ett filteruttryck som bara returnerar de hotell med ett omdöme som är större än fyra, sorterat i fallande ordning.
  • Fältomfång: Lägg till search_fields i omfånget för frågekörning till specifika fält.
  • Fasetter: Generera fasetter för positiva matchningar som finns i sökresultat. Det finns inga noll matchningar. Om sökresultaten inte innehåller termen wifi visas inte wifi i den fasetterade navigeringsstrukturen.
  • Slå upp ett dokument: Returnera ett dokument baserat på dess nyckel. Den här åtgärden är användbar om du vill visa detaljerad information när en användare väljer ett objekt i ett sökresultat.
  • Komplettera automatiskt: Ange potentiella matchningar när användaren skriver i sökrutan. Autocomplete använder en suggester (sg) för att veta vilka fält som innehåller potentiella matchningar för förslagsbegäranden. I den här snabbstarten är Tagsfälten , Address/City, Address/Country. Om du vill simulera automatisk komplettering skickar du bokstäverna sa som en partiell sträng. Metoden för automatisk komplettering av SearchClient skickar tillbaka potentiella termmatchningar.

Ta bort indexet

Om du är klar med det här indexet kan du ta bort det genom att köra cellen Rensa kod. Om du tar bort onödiga index frigörs utrymme för att gå igenom fler snabbstarter och självstudier.

Lär dig hur du använder klientbiblioteket Azure.Search.Documents för att skapa, läsa in och köra frågor mot ett sökindex med hjälp av exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor samt en BM25-rangordningsalgoritm för bedömning av resultat.

Den här snabbstarten skapar och frågar ett litet hotell-snabbstartsindex som innehåller data om fyra hotell.

Dricks

Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.

Förutsättningar

  • En aktiv Azure-prenumeration – Skapa en kostnadsfritt
  • En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. Du kan använda en kostnadsfri nivå för den här snabbstarten.

Krav för Microsoft Entra-ID

För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:

  • Installera Azure CLI som används för nyckellös autentisering med Microsoft Entra-ID.
  • Tilldela både rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.

Hämta resursinformation

Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:

Variabelnamn Värde
SEARCH_API_ENDPOINT Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn. Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

Läs mer om nyckellös autentisering och inställning av miljövariabler.

Konfigurera

  1. Skapa en ny mapp full-text-quickstart som ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. package.json Skapa med följande kommando:

    npm init -y
    
  3. package.json Uppdatera till ECMAScript med följande kommando:

    npm pkg set type=module
    
  4. Installera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för JavaScript med:

    npm install @azure/search-documents
    
  5. För den rekommenderade lösenordslösa autentiseringen installerar du Azure Identity-klientbiblioteket med:

    npm install @azure/identity
    

Skapa, läsa in och fråga ett sökindex

I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.

I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .

Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.

const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
  1. Skapa en ny fil med namnet index.ts och klistra in följande kod i 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. Skapa en fil med namnet hotels.json och klistra in följande kod i 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. tsconfig.json Skapa filen för att transpilera TypeScript-koden och kopiera följande kod för ECMAScript.

    {
        "compilerOptions": {
          "module": "NodeNext",
          "target": "ES2022", // Supports top-level await
          "moduleResolution": "NodeNext",
          "skipLibCheck": true, // Avoid type errors from node_modules
          "strict": true // Enable strict type-checking options
        },
        "include": ["*.ts"]
    }
    
  4. Transpilera från TypeScript till JavaScript.

    tsc
    
  5. Logga in på Azure med följande kommando:

    az login
    
  6. Kör JavaScript-koden med följande kommando:

    node index.js
    

Förklara koden

Skapa index

Skapa en fil hotels_quickstart_index.json. Den här filen definierar hur Azure AI Search fungerar med de dokument som du läser in i nästa steg. Varje fält identifieras av en name och har en angiven type. Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).

Vi vill importera hotels_quickstart_index.json så att huvudfunktionen kan komma åt indexdefinitionen.

import indexDefinition from './hotels_quickstart_index.json';

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

I huvudfunktionen skapar vi sedan en SearchIndexClient, som används för att skapa och hantera index för Azure AI Search.

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

Sedan vill vi ta bort indexet om det redan finns. Den här åtgärden är en vanlig metod för test-/demokod.

Det gör vi genom att definiera en enkel funktion som försöker ta bort 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.');
    }
}

För att köra funktionen extraherar vi indexnamnet från indexdefinitionen och skickar indexName med indexClient till deleteIndexIfExists() funktionen.

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

Efter det är vi redo att skapa indexet med createIndex() -metoden.

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

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

Läsa in dokument

I Azure AI Search är dokument datastrukturer som både är indata för indexering och utdata från frågor. Du kan skicka sådana data till indexet eller använda en indexerare. I det här fallet skickar vi programmatiskt dokumenten till indexet.

Dokumentindata kan vara rader i en databas, blobar i Blob Storage eller, som i det här exemplet, JSON-dokument på disk. Du kan antingen ladda ned hotels.json eller skapa en egen hotels.json fil med följande innehåll:

På samma sätt som vi gjorde med indexDefinition måste vi också importera hotels.json överst i index.ts så att data kan nås i vår huvudfunktion.

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"];

För att indexera data i sökindexet måste vi nu skapa en SearchClient. SearchIndexClient Används för att skapa och hantera ett index, SearchClient men används för att ladda upp dokument och köra frågor mot indexet.

Det finns två sätt att skapa en SearchClient. Det första alternativet är att skapa en SearchClient från grunden:

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

Du kan också använda getSearchClient() metoden SearchIndexClient för för att skapa SearchClient:

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

Nu när klienten har definierats laddar du upp dokumenten till sökindexet. I det här fallet använder mergeOrUploadDocuments() vi metoden som laddar upp dokumenten eller sammanfogar dem med ett befintligt dokument om det redan finns ett dokument med samma nyckel. Kontrollera sedan att åtgärden lyckades eftersom åtminstone det första dokumentet finns.

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

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

Kör programmet igen med tsc && node index.ts. Du bör se en något annorlunda uppsättning meddelanden än de du såg i steg 1. Den här gången finns indexet och du bör se ett meddelande om att ta bort det innan appen skapar det nya indexet och publicerar data till det.

Innan vi kör frågorna i nästa steg definierar du en funktion så att programmet väntar en sekund. Detta görs bara i test-/demosyfte för att säkerställa att indexeringen är klar och att dokumenten är tillgängliga i indexet för våra frågor.

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

Om du vill att programmet ska vänta en sekund anropar du sleep funktionen:

sleep(1000);

Sök i ett index

När ett index har skapats och dokument har laddats upp är du redo att skicka frågor till indexet. I det här avsnittet skickar vi fem olika frågor till sökindexet för att demonstrera olika frågefunktioner som är tillgängliga för dig.

Frågorna skrivs i en sendQueries() funktion som vi anropar i huvudfunktionen enligt följande:

await sendQueries(searchClient);

Frågor skickas med metoden search()searchClient. Den första parametern är söktexten och den andra parametern anger sökalternativ.

Frågeexempel 1

Den första frågan söker efter *, vilket motsvarar att söka efter allt och väljer tre av fälten i indexet. Det är en bra idé att bara select använda de fält du behöver eftersom onödiga data kan ge svarstid till dina frågor.

För searchOptions den här frågan har includeTotalCount också angetts till true, vilket returnerar antalet matchande resultat som hittades.

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
}

De återstående frågorna som beskrivs nedan bör också läggas till i sendQueries() funktionen. De är separerade här för läsbarhet.

Frågeexempel 2

I nästa fråga anger vi söktermen "wifi" och inkluderar även ett filter för att endast returnera resultat där tillståndet är lika med 'FL'. Resultaten beställs också av hotellets 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)}`);
}

Frågeexempel 3

Därefter begränsas sökningen till ett enda sökbart fält med hjälp av parametern searchFields . Den här metoden är ett bra alternativ för att göra frågan mer effektiv om du vet att du bara är intresserad av matchningar i vissa fält.

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

Frågeexempel 4

Ett annat vanligt alternativ att ta med i en fråga är facets. Med fasetter kan du tillhandahålla självriktad detaljvisning från resultatet i användargränssnittet. Fasetteringsresultatet kan omvandlas till kryssrutor i resultatfönstret.

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

Frågeexempel 5

Den sista frågan använder getDocument() metoden för searchClient. På så sätt kan du effektivt hämta ett dokument med dess nyckel.

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

Sammanfattning av frågor

Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.

Fulltextsökning och -filter utförs med hjälp av searchClient.search metoden . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter klassens SearchOptions egenskap. Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.

Rensa resurser

När du arbetar i din egen prenumeration kan det dock vara klokt att i slutet av ett projekt kontrollera om du fortfarande behöver de resurser som du skapade. Resurser som fortsätter att köras kostar pengar. Du kan ta bort enstaka resurser eller hela resursgruppen om du vill ta bort alla resurser.

Du kan hitta och hantera resurser i Azure Portal med hjälp av länken Alla resurser eller Resursgrupper i det vänstra navigeringsfönstret.

Om du använder en kostnadsfri tjänst ska du komma ihåg att du är begränsad till tre index, indexerare och datakällor. Du kan ta bort enskilda objekt i Azure Portal för att hålla dig under gränsen.

Gå vidare

I den här snabbstarten arbetade du med en uppsättning uppgifter för att skapa ett index, läsa in det med dokument och köra frågor. I olika steg tog vi genvägar för att förenkla koden för läsbarhet och förståelse. Nu när du är bekant med de grundläggande begreppen kan du prova en självstudiekurs som anropar API:erna för Azure AI Search i en webbapp.