Delen via


Snelstart: Zoeken in volledige tekst

In deze quickstart gebruikt u de clientbibliotheek Azure.Search.Documents om een zoekindex te maken, laden en er query's op uit te voeren met voorbeeldgegevens voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Vereisten voor Microsoft Entra-id

Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:

Resourcegegevens ophalen

U moet de volgende informatie ophalen om uw toepassing te verifiëren met uw Azure AI-Search-service:

Naam van de variabele Weergegeven als
SEARCH_API_ENDPOINT Deze waarde vindt u in Azure Portal. Selecteer uw zoekservice en selecteer vervolgens in het linkermenu Overzicht. De URL-waarde onder Essentials is het eindpunt dat u nodig hebt. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

Meer informatie over sleutelloze verificatie en het instellen van omgevingsvariabelen.

Instellingen

  1. Maak een nieuwe map full-text-quickstart die de toepassing bevat en open Visual Studio Code in die map met de volgende opdracht:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Maak een nieuwe consoletoepassing met de volgende opdracht:

    dotnet new console
    
  3. Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor .NET met:

    dotnet add package Azure.Search.Documents
    
  4. Voor de aanbevolen sleutelloze verificatie met Microsoft Entra ID installeert u het Azure.Identity-pakket met:

    dotnet add package Azure.Identity
    
  5. Meld u met de volgende opdracht aan bij Azure voor de aanbevolen sleutelloze verificatie met Microsoft Entra ID:

    az login
    

Een zoekindex maken, laden en er query's op uitvoeren

In de vorige sectie voor het instellen hebt u een nieuwe consoletoepassing gemaakt en de Azure AI Search-clientbibliotheek geïnstalleerd.

In deze sectie voegt u code toe om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U voert het programma uit om de resultaten in de console te zien. Zie de uitleg van de codesectie voor een gedetailleerde uitleg van de code .

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
  1. Plak in Program.cs de volgende code. Bewerk de serviceName en apiKey variabelen met de naam en de beheer-API-sleutel van uw zoekservice.

    using System;
    using Azure;
    using Azure.Identity;
    using Azure.Search.Documents;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    using Azure.Search.Documents.Models;
    
    namespace AzureSearch.Quickstart
    
    {
        class Program
        {
            static void Main(string[] args)
            {    
                // Your search service endpoint
                Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
    
                // Use the recommended keyless credential instead of the AzureKeyCredential credential.
                DefaultAzureCredential credential = new();
                //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
    
                // Create a SearchIndexClient to send create/delete index commands
                SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential);
    
                // Create a SearchClient to load and query documents
                string indexName = "hotels-quickstart";
                SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential);
    
                // Delete index if it exists
                Console.WriteLine("{0}", "Deleting index...\n");
                DeleteIndexIfExists(indexName, searchIndexClient);
    
                // Create index
                Console.WriteLine("{0}", "Creating index...\n");
                CreateIndex(indexName, searchIndexClient);
    
                SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);
    
                // Load documents
                Console.WriteLine("{0}", "Uploading documents...\n");
                UploadDocuments(ingesterClient);
    
                // Wait 2 secondsfor indexing to complete before starting queries (for demo and console-app purposes only)
                Console.WriteLine("Waiting for indexing...\n");
                System.Threading.Thread.Sleep(2000);
    
                // Call the RunQueries method to invoke a series of queries
                Console.WriteLine("Starting queries...\n");
                RunQueries(searchClient);
    
                // End the program
                Console.WriteLine("{0}", "Complete. Press any key to end this program...\n");
                Console.ReadKey();
            }
    
            // Delete the hotels-quickstart index to reuse its name
            private static void DeleteIndexIfExists(string indexName, SearchIndexClient searchIndexClient)
            {
                searchIndexClient.GetIndexNames();
                {
                    searchIndexClient.DeleteIndex(indexName);
                }
            }
            // Create hotels-quickstart index
            private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient)
            {
                FieldBuilder fieldBuilder = new FieldBuilder();
                var searchFields = fieldBuilder.Build(typeof(Hotel));
    
                var definition = new SearchIndex(indexName, searchFields);
    
                var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
                definition.Suggesters.Add(suggester);
    
                searchIndexClient.CreateOrUpdateIndex(definition);
            }
    
            // Upload documents in a single Upload request.
            private static void UploadDocuments(SearchClient searchClient)
            {
                IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
                    IndexDocumentsAction.Upload(
                        new Hotel()
                        {
                            HotelId = "1",
                            HotelName = "Stay-Kay City Hotel",
                            Description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                            Category = "Boutique",
                            Tags = new[] { "view", "air conditioning", "concierge" },
                            ParkingIncluded = false,
                            LastRenovationDate = new DateTimeOffset(2022, 1, 18, 0, 0, 0, TimeSpan.Zero),
                            Rating = 3.6,
                            Address = new Address()
                            {
                                StreetAddress = "677 5th Ave",
                                City = "New York",
                                StateProvince = "NY",
                                PostalCode = "10022",
                                Country = "USA"
                            }
                        }),
                    IndexDocumentsAction.Upload(
                        new Hotel()
                        {
                            HotelId = "2",
                            HotelName = "Old Century Hotel",
                            Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                            Category = "Boutique",
                            Tags = new[] { "pool", "free wifi", "concierge" },
                            ParkingIncluded = false,
                            LastRenovationDate = new DateTimeOffset(2019, 2, 18, 0, 0, 0, TimeSpan.Zero),
                            Rating = 3.60,
                            Address = new Address()
                            {
                                StreetAddress = "140 University Town Center Dr",
                                City = "Sarasota",
                                StateProvince = "FL",
                                PostalCode = "34243",
                                Country = "USA"
                            }
                        }),
                    IndexDocumentsAction.Upload(
                        new Hotel()
                        {
                            HotelId = "3",
                            HotelName = "Gastronomic Landscape Hotel",
                            Description = "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                            Category = "Suite",
                            Tags = new[] { "restaurant", "bar", "continental breakfast" },
                            ParkingIncluded = true,
                            LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero),
                            Rating = 4.80,
                            Address = new Address()
                            {
                                StreetAddress = "3393 Peachtree Rd",
                                City = "Atlanta",
                                StateProvince = "GA",
                                PostalCode = "30326",
                                Country = "USA"
                            }
                        }),
                    IndexDocumentsAction.Upload(
                        new Hotel()
                        {
                            HotelId = "4",
                            HotelName = "Sublime Palace Hotel",
                            Description = "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                            Category = "Boutique",
                            Tags = new[] { "concierge", "view", "air conditioning" },
                            ParkingIncluded = true,
                            LastRenovationDate = new DateTimeOffset(2020, 2, 06, 0, 0, 0, TimeSpan.Zero),
                            Rating = 4.60,
                            Address = new Address()
                            {
                                StreetAddress = "7400 San Pedro Ave",
                                City = "San Antonio",
                                StateProvince = "TX",
                                PostalCode = "78216",
                                Country = "USA"
                            }
                        })
                    );
    
                try
                {
                    IndexDocumentsResult result = searchClient.IndexDocuments(batch);
                }
                catch (Exception)
                {
                    // If for some reason any documents are dropped during indexing, you can compensate by delaying and
                    // retrying. This simple demo just logs the failed document keys and continues.
                    Console.WriteLine("Failed to index some of the documents: {0}");
                }
            }
    
            // Run queries, use WriteDocuments to print output
            private static void RunQueries(SearchClient searchClient)
            {
                SearchOptions options;
                SearchResults<Hotel> response;
    
                // Query 1
                Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
    
                options = new SearchOptions()
                {
                    IncludeTotalCount = true,
                    Filter = "",
                    OrderBy = { "" }
                };
    
                options.Select.Add("HotelId");
                options.Select.Add("HotelName");
                options.Select.Add("Rating");
    
                response = searchClient.Search<Hotel>("*", options);
                WriteDocuments(response);
    
                // Query 2
                Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
    
                options = new SearchOptions()
                {
                    Filter = "Rating gt 4",
                    OrderBy = { "Rating desc" }
                };
    
                options.Select.Add("HotelId");
                options.Select.Add("HotelName");
                options.Select.Add("Rating");
    
                response = searchClient.Search<Hotel>("hotels", options);
                WriteDocuments(response);
    
                // Query 3
                Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n");
    
                options = new SearchOptions()
                {
                    SearchFields = { "Tags" }
                };
    
                options.Select.Add("HotelId");
                options.Select.Add("HotelName");
                options.Select.Add("Tags");
    
                response = searchClient.Search<Hotel>("pool", options);
                WriteDocuments(response);
    
                // Query 4 - Use Facets to return a faceted navigation structure for a given query
                // Filters are typically used with facets to narrow results on OnClick events
                Console.WriteLine("Query #4: Facet on 'Category'...\n");
    
                options = new SearchOptions()
                {
                    Filter = ""
                };
    
                options.Facets.Add("Category");
    
                options.Select.Add("HotelId");
                options.Select.Add("HotelName");
                options.Select.Add("Category");
    
                response = searchClient.Search<Hotel>("*", options);
                WriteDocuments(response);
    
                // Query 5
                Console.WriteLine("Query #5: Look up a specific document...\n");
    
                Response<Hotel> lookupResponse;
                lookupResponse = searchClient.GetDocument<Hotel>("3");
    
                Console.WriteLine(lookupResponse.Value.HotelId);
    
    
                // Query 6
                Console.WriteLine("Query #6: Call Autocomplete on HotelName...\n");
    
                var autoresponse = searchClient.Autocomplete("sa", "sg");
                WriteDocuments(autoresponse);
    
            }
    
            // Write search results to console
            private static void WriteDocuments(SearchResults<Hotel> searchResults)
            {
                foreach (SearchResult<Hotel> result in searchResults.GetResults())
                {
                    Console.WriteLine(result.Document);
                }
    
                Console.WriteLine();
            }
    
            private static void WriteDocuments(AutocompleteResults autoResults)
            {
                foreach (AutocompleteItem result in autoResults.Results)
                {
                    Console.WriteLine(result.Text);
                }
    
                Console.WriteLine();
            }
        }
    }
    
  2. Maak in dezelfde map een nieuw bestand met de naam Hotel.cs en plak de volgende code. Deze code definieert de structuur van een hoteldocument.

    using System;
    using System.Text.Json.Serialization;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            [SimpleField(IsKey = true, IsFilterable = true)]
            public string HotelId { get; set; }
    
            [SearchableField(IsSortable = true)]
            public string HotelName { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
            public string Description { get; set; }
    
            [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public string Category { get; set; }
    
            [SearchableField(IsFilterable = true, IsFacetable = true)]
            public string[] Tags { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public bool? ParkingIncluded { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public DateTimeOffset? LastRenovationDate { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public double? Rating { get; set; }
    
            [SearchableField]
            public Address Address { get; set; }
        }
    }
    
  3. Maak een nieuw bestand met de naam Hotel.cs en plak de volgende code om de structuur van een hoteldocument te definiëren. Kenmerken in het veld bepalen hoe deze worden gebruikt in een toepassing. Het IsFilterable-kenmerk moet bijvoorbeeld worden toegewezen aan elk veld dat een filterexpressie ondersteunt.

    using System;
    using System.Text.Json.Serialization;
    using Azure.Search.Documents.Indexes;
    using Azure.Search.Documents.Indexes.Models;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            [SimpleField(IsKey = true, IsFilterable = true)]
            public string HotelId { get; set; }
    
            [SearchableField(IsSortable = true)]
            public string HotelName { get; set; }
    
            [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
            public string Description { get; set; }
    
            [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public string Category { get; set; }
    
            [SearchableField(IsFilterable = true, IsFacetable = true)]
            public string[] Tags { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public bool? ParkingIncluded { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public DateTimeOffset? LastRenovationDate { get; set; }
    
            [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
            public double? Rating { get; set; }
    
            [SearchableField]
            public Address Address { get; set; }
        }
    }
    
  4. Maak een nieuw bestand met de naam Address.cs en plak de volgende code om de structuur van een adresdocument te definiëren.

    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. Maak een nieuw bestand met de naam Hotel.Methods.cs en plak de volgende code om een ToString() onderdrukking voor de Hotel klasse te definiëren.

    using System;
    using System.Text;
    
    namespace AzureSearch.Quickstart
    {
        public partial class Hotel
        {
            public override string ToString()
            {
                var builder = new StringBuilder();
    
                if (!String.IsNullOrEmpty(HotelId))
                {
                    builder.AppendFormat("HotelId: {0}\n", HotelId);
                }
    
                if (!String.IsNullOrEmpty(HotelName))
                {
                    builder.AppendFormat("Name: {0}\n", HotelName);
                }
    
                if (!String.IsNullOrEmpty(Description))
                {
                    builder.AppendFormat("Description: {0}\n", Description);
                }
    
                if (!String.IsNullOrEmpty(Category))
                {
                    builder.AppendFormat("Category: {0}\n", Category);
                }
    
                if (Tags != null && Tags.Length > 0)
                {
                    builder.AppendFormat("Tags: [ {0} ]\n", String.Join(", ", Tags));
                }
    
                if (ParkingIncluded.HasValue)
                {
                    builder.AppendFormat("Parking included: {0}\n", ParkingIncluded.Value ? "yes" : "no");
                }
    
                if (LastRenovationDate.HasValue)
                {
                    builder.AppendFormat("Last renovated on: {0}\n", LastRenovationDate);
                }
    
                if (Rating.HasValue)
                {
                    builder.AppendFormat("Rating: {0}\n", Rating);
                }
    
                if (Address != null && !Address.IsEmpty)
                {
                    builder.AppendFormat("Address: \n{0}\n", Address.ToString());
                }
    
                return builder.ToString();
            }
        }
    }
    
  6. Maak een nieuw bestand met de naam Address.Methods.cs en plak de volgende code om een ToString() onderdrukking voor de Address klasse te definiëren.

    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. Bouw en voer de toepassing uit met de volgende opdracht:

    dotnet run
    

De uitvoer bevat berichten van Console.WriteLine, met toevoeging van query-informatie en -resultaten.

Uitleg van de code

In de vorige secties hebt u een nieuwe consoletoepassing gemaakt en de Azure AI Search-clientbibliotheek geïnstalleerd. U hebt code toegevoegd om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U hebt het programma uitgevoerd om de resultaten in de console te zien.

In deze sectie wordt de code uitgelegd die u hebt toegevoegd aan de consoletoepassing.

Een zoekclient maken

In Program.cs hebt u twee clients gemaakt:

Beide clients hebben het eindpunt van de zoekservice en referenties nodig die eerder zijn beschreven in de sectie resourcegegevens .

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

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

Een index maken

Deze quickstart bouwt een Hotels-index die u laadt met hotelgegevens en voert query's uit op. In deze stap definieert u de velden in de index. Elke definitie bevat een naam, gegevenstype en kenmerken die bepalen hoe het veld wordt gebruikt.

In dit voorbeeld worden synchrone methoden van de bibliotheek Azure.Search.Documents gebruikt voor eenvoud en leesbaarheid. Voor productiescenario's moet u echter asynchrone methoden gebruiken om uw app op een schaalbare en responsieve manier te laten werken. U kunt bijvoorbeeld CreateIndexAsync gebruiken in plaats van CreateIndex.

De structuren definiëren

U hebt twee helperklassen gemaakt, Hotel.cs en Address.cs, om de structuur van een hoteldocument en het bijbehorende adres te definiëren. De Hotel klasse bevat velden voor een hotel-id, naam, beschrijving, categorie, tags, parkeren, renovatiedatum, classificatie en adres. De Address klasse bevat velden voor adres, plaats, provincie, postcode en land/regio.

In de clientbibliotheek Azure.Search.Documents kunt u SearchableField en SimpleField gebruiken om velddefinities te stroomlijnen. Beide zijn afgeleiden van een SearchField en kunnen uw code vereenvoudigen:

  • SimpleField kan elk gegevenstype zijn, is altijd niet doorzoekbaar (genegeerd voor zoekquery's in volledige tekst) en kan worden opgehaald (niet verborgen). Andere kenmerken zijn standaard uitgeschakeld, maar kunnen wel worden ingeschakeld. U kunt een SimpleField gebruiken voor document-id's of velden die alleen worden gebruikt in filters, facetten of scoreprofielen. Als dat het geval is, moet u ervoor zorgen dat u alle kenmerken toepast die nodig zijn voor het scenario, zoals IsKey = true voor een document-id. Zie SimpleFieldAttribute.cs in broncode voor meer informatie.

  • SearchableField moet een tekenreeks zijn die altijd kan worden doorzocht en opgehaald. Andere kenmerken zijn standaard uitgeschakeld, maar kunnen wel worden ingeschakeld. Omdat dit veldtype kan worden doorzocht, worden synoniemen en het volledige gamma van analyse-eigenschappen ondersteund. Zie SearchableFieldAttribute.cs in broncode voor meer informatie.

Ongeacht of u de basis-API van SearchField of een van de hulpmodellen gebruikt, u moet filter-, facet- en sorteerkenmerken expliciet inschakelen. IsFilterable, IsSortable en IsFacetable moeten bijvoorbeeld expliciet worden toegeschreven, zoals wordt weergegeven in het vorige voorbeeld.

De zoekindex maken

In Program.cs maakt u een SearchIndex-object en roept u vervolgens de methode CreateIndex aan om de index in uw zoekservice uit te drukken. De index bevat ook een SearchSuggester om automatisch aanvullen in te schakelen voor de opgegeven velden.

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

Documenten laden

Azure AI Search zoekt naar inhoud die is opgeslagen in de service. In deze stap laadt u JSON-documenten die voldoen aan de hotelindex die u hebt gemaakt.

In Azure AI Search zijn zoekdocumenten gegevensstructuren die zowel invoer zijn voor het indexeren als uitvoeren van query's. Als u de documenten hebt verkregen via een externe gegevensbron, bestaat de documentinvoer mogelijk uit rijen in een database, blobs in Blob Storage of JSON-documenten op een schijf. In dit voorbeeld nemen we de korte route en gaan we JSON-documenten voor vier hotels in de code zelf insluiten.

Bij het uploaden van documenten moet u een IndexDocumentsBatch-object gebruiken. Een IndexDocumentsBatch object bevat een verzameling acties, die elk een document en een eigenschap bevatten die Azure AI Search vertelt welke actie moet worden uitgevoerd (uploaden, samenvoegen, verwijderen en samenvoegen).

In Program.cs maakt u een matrix met documenten en indexacties en geeft u de matrix vervolgens door aan IndexDocumentsBatch. De volgende documenten voldoen aan de index hotels-quickstart, zoals gedefinieerd door de hotelklasse.

// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
    IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(
            new Hotel()
            {
                HotelId = "1",
                HotelName = "Stay-Kay City Hotel",
                Description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                Category = "Boutique",
                Tags = new[] { "view", "air conditioning", "concierge" },
                ParkingIncluded = false,
                LastRenovationDate = new DateTimeOffset(2022, 1, 18, 0, 0, 0, TimeSpan.Zero),
                Rating = 3.6,
                Address = new Address()
                {
                    StreetAddress = "677 5th Ave",
                    City = "New York",
                    StateProvince = "NY",
                    PostalCode = "10022",
                    Country = "USA"
                }
            }),
        // REDACTED FOR BREVITY
}

Nadat u het IndexDocumentsBatch-object hebt geïnitialiseerd, kunt u het naar de index sturen door IndexDocuments aan te roepen op uw SearchClient-object.

U laadt documenten met SearchClient in Main(), maar voor de bewerking zijn ook beheerdersrechten vereist voor de service, die doorgaans is gekoppeld aan SearchIndexClient. Een manier om deze bewerking in te stellen, is door SearchClient door SearchIndexClient te halen (searchIndexClient in dit voorbeeld).

SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);

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

Omdat we een console-app hebben waarmee alle opdrachten opeenvolgend worden uitgevoerd, voegen we een wachttijd van 2 seconden toe tussen indexering en query's.

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

De vertraging van 2 seconden compenseert de indexering (die asynchroon is), zodat alle documenten kunnen worden geïndexeerd voordat de query's worden uitgevoerd. Codering in een vertraging is doorgaans alleen nodig in demo's, testen en voorbeeldtoepassingen.

Een index doorzoeken

U kunt queryresultaten ophalen zodra het eerste document wordt geïndexeerd, maar wacht met het daadwerkelijk testen van uw index totdat alle documenten zijn geïndexeerd.

In deze sectie worden twee functies toegevoegd: querylogica en resultaten. Gebruik voor query's de methode Search. Deze methode gebruikt zoektekst (de querytekenreeks) en andere opties.

De SearchResults-klasse vertegenwoordigt de resultaten.

In Program.cs drukt de WriteDocuments methode zoekresultaten af op de console.

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

Queryvoorbeeld 1

De RunQueries methode voert query's uit en retourneert resultaten. Resultaten zijn Hotel-objecten. In dit voorbeeld ziet u de handtekening en de eerste query van de methode. Deze query demonstreert de Select parameter waarmee u het resultaat kunt opstellen met behulp van geselecteerde velden uit het document.

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

Queryvoorbeeld 2

In de tweede query zoekt u op een term, voegt u een filter toe waarmee documenten worden geselecteerd waarin Waardering groter is dan 4 en vervolgens in aflopende volgorde op Classificatie sorteren. Een filter is een Booleaanse uitdrukking die wordt geëvalueerd over IsFilterable-velden in een index. Filterquery's bevatten waarden of sluiten ze uit. Er is dus geen relevantiescore gekoppeld aan een filterquery.

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

Queryvoorbeeld 3

De derde query laat zien searchFields, dat wordt gebruikt om een zoekbewerking voor volledige tekst te bepalen voor specifieke velden.

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

Queryvoorbeeld 4

De vierde query laat zien facets, die kan worden gebruikt om een facetnavigatiestructuur te structuren.

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

Queryvoorbeeld 5

In de vijfde query retourneert u een specifiek document. Een documentzoekactie is een typisch antwoord op OnClick gebeurtenissen in een resultatenset.

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

Queryvoorbeeld 6

De laatste query toont de syntaxis voor automatisch aanvullen en simuleert een gedeeltelijke gebruikersinvoer van sa die wordt omgezet in twee mogelijke overeenkomsten in de bronvelden die zijn gekoppeld aan de suggestie die u in de index hebt gedefinieerd.

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

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

Samenvatting van query's

De vorige query's tonen meerdere manieren om termen in een query te koppelen: zoekopdracht in volledige tekst, filters en automatisch aanvullen.

Zoekopdrachten in volledige tekst en filters worden uitgevoerd met behulp van de methode SearchClient.Search. Een zoekquery kan worden doorgegeven in de searchText-tekenreeks, terwijl een filterexpressie kan worden doorgegeven in de eigenschap Filter van de klasse Search Options. Als u wilt filteren zonder te zoeken, geeft u "*" door voor de searchText-parameter van de Zoekmethode. Als u wilt zoeken zonder te filteren, laat u de Filter eigenschap uitgeschakeld of geeft u een SearchOptions instantie helemaal niet door.

In deze quickstart gebruikt u de clientbibliotheek Azure.Search.Documents om een zoekindex te maken, laden en er query's op uit te voeren met voorbeeldgegevens voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Vereisten voor Microsoft Entra-id

Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:

Resourcegegevens ophalen

U moet de volgende informatie ophalen om uw toepassing te verifiëren met uw Azure AI-Search-service:

Naam van de variabele Weergegeven als
SEARCH_API_ENDPOINT Deze waarde vindt u in Azure Portal. Selecteer uw zoekservice en selecteer vervolgens in het linkermenu Overzicht. De URL-waarde onder Essentials is het eindpunt dat u nodig hebt. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

Meer informatie over sleutelloze verificatie en het instellen van omgevingsvariabelen.

Instellingen

Het voorbeeld in deze quickstart werkt met de Java Runtime. Installeer een Java Development Kit zoals Azul Zulu OpenJDK. De Microsoft Build van OpenJDK of uw favoriete JDK moet ook werken.

  1. Installeer Apache Maven. Voer vervolgens uit mvn -v om de installatie te bevestigen.

  2. Maak een nieuw pom.xml bestand in de hoofdmap van uw project en kopieer de volgende code erin:

    <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. Installeer de afhankelijkheden, waaronder de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor Java- en Azure Identity-clientbibliotheek voor Java met:

    mvn clean dependency:copy-dependencies
    
  4. Meld u met de volgende opdracht aan bij Azure voor de aanbevolen sleutelloze verificatie met Microsoft Entra ID:

    az login
    

Een zoekindex maken, laden en er query's op uitvoeren

In de vorige sectie voor het instellen hebt u de Azure AI Search-clientbibliotheek en andere afhankelijkheden geïnstalleerd.

In deze sectie voegt u code toe om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U voert het programma uit om de resultaten in de console te zien. Zie de uitleg van de codesectie voor een gedetailleerde uitleg van de code .

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Maak een nieuw bestand met de naam App.java en plak de volgende code in 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 = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "view", "air conditioning", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2022, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 3.6;
            hotel.address = new Address();
            hotel.address.streetAddress = "677 5th Ave";
            hotel.address.city = "New York";
            hotel.address.stateProvince = "NY";
            hotel.address.postalCode = "10022";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "2";
            hotel.hotelName = "Old Century Hotel";
            hotel.description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
            hotel.category = "Boutique";
            hotel.tags = new String[] { "pool", "free wifi", "concierge" };
            hotel.parkingIncluded = false;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2019, 2, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 3.60;
            hotel.address = new Address();
            hotel.address.streetAddress = "140 University Town Center Dr";
            hotel.address.city = "Sarasota";
            hotel.address.stateProvince = "FL";
            hotel.address.postalCode = "34243";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "3";
            hotel.hotelName = "Gastronomic Landscape Hotel";
            hotel.description = "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.";
            hotel.category = "Suite";
            hotel.tags = new String[] { "restaurant", "bar", "continental breakfast" };
            hotel.parkingIncluded = true;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2015, 9, 20), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 4.80;
            hotel.address = new Address();
            hotel.address.streetAddress = "3393 Peachtree Rd";
            hotel.address.city = "Atlanta";
            hotel.address.stateProvince = "GA";
            hotel.address.postalCode = "30326";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            hotel = new Hotel();
            hotel.hotelId = "4";
            hotel.hotelName = "Sublime Palace Hotel";
            hotel.description = "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.";
            hotel.category = "Boutique";
            hotel.tags = new String[] { "concierge", "view", "air conditioning" };
            hotel.parkingIncluded = true;
            hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2020, 2, 06), LocalTime.of(0, 0)), ZoneOffset.UTC);
            hotel.rating = 4.60;
            hotel.address = new Address();
            hotel.address.streetAddress = "7400 San Pedro Ave";
            hotel.address.city = "San Antonio";
            hotel.address.stateProvince = "TX";
            hotel.address.postalCode = "78216";
            hotel.address.country = "USA";
            hotelList.add(hotel);
    
            var batch = new IndexDocumentsBatch<Hotel>();
            batch.addMergeOrUploadActions(hotelList);
            try
            {
                searchClient.indexDocuments(batch);
            }
            catch (Exception e)
            {
                e.printStackTrace();
                // If for some reason any documents are dropped during indexing, you can compensate by delaying and
                // retrying. This simple demo just logs failure and continues
                System.err.println("Failed to index some of the documents");
            }
        }
    
        // Write search results to console
        private static void WriteSearchResults(SearchPagedIterable searchResults)
        {
            searchResults.iterator().forEachRemaining(result ->
            {
                Hotel hotel = result.getDocument(Hotel.class);
                System.out.println(hotel);
            });
    
            System.out.println();
        }
    
        // Write autocomplete results to console
        private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
        {
            autocompleteResults.iterator().forEachRemaining(result ->
            {
                String text = result.getText();
                System.out.println(text);
            });
    
            System.out.println();
        }
    
        // Run queries, use WriteDocuments to print output
        private static void RunQueries(SearchClient searchClient)
        {
            // Query 1
            System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
    
            SearchOptions options = new SearchOptions();
            options.setIncludeTotalCount(true);
            options.setFilter("");
            options.setOrderBy("");
            options.setSelect("HotelId", "HotelName", "Address/City");
    
            WriteSearchResults(searchClient.search("*", options, Context.NONE));
    
            // Query 2
            System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
    
            options = new SearchOptions();
            options.setFilter("Rating gt 4");
            options.setOrderBy("Rating desc");
            options.setSelect("HotelId", "HotelName", "Rating");
    
            WriteSearchResults(searchClient.search("hotels", options, Context.NONE));
    
            // Query 3
            System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");
    
            options = new SearchOptions();
            options.setSearchFields("Tags");
    
            options.setSelect("HotelId", "HotelName", "Tags");
    
            WriteSearchResults(searchClient.search("pool", options, Context.NONE));
    
            // Query 4
            System.out.println("Query #4: Facet on 'Category'...\n");
    
            options = new SearchOptions();
            options.setFilter("");
            options.setFacets("Category");
            options.setSelect("HotelId", "HotelName", "Category");
    
            WriteSearchResults(searchClient.search("*", options, Context.NONE));
    
            // Query 5
            System.out.println("Query #5: Look up a specific document...\n");
    
            Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
            System.out.println(lookupResponse.hotelId);
            System.out.println();
    
             // Query 6
            System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
    
            WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
        }
    }
    
  2. Maak een nieuw bestand met de naam Hotel.java en plak de volgende code in 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;
    
        /**
         * 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. Maak een nieuw bestand met de naam Address.java en plak de volgende code in 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. Voer de nieuwe consoletoepassing uit:

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

Uitleg van de code

In de vorige secties hebt u een nieuwe consoletoepassing gemaakt en de Azure AI Search-clientbibliotheek geïnstalleerd. U hebt code toegevoegd om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U hebt het programma uitgevoerd om de resultaten in de console te zien.

In deze sectie wordt de code uitgelegd die u hebt toegevoegd aan de consoletoepassing.

Een zoekclient maken

In App.java hebt u twee clients gemaakt:

  • SearchIndexClient maakt de index.
  • SearchClient laadt en voert query's uit op een bestaande index.

Beide clients hebben het eindpunt van de zoekservice en referenties nodig die eerder zijn beschreven in de sectie resourcegegevens.

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

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

Een index maken

Deze quickstart bouwt een Hotels-index die u laadt met hotelgegevens en voert query's uit op. In deze stap definieert u de velden in de index. Elke definitie bevat een naam, gegevenstype en kenmerken die bepalen hoe het veld wordt gebruikt.

In dit voorbeeld worden synchrone methoden van de bibliotheek Azure.Search.Documents gebruikt voor eenvoud en leesbaarheid. Voor productiescenario's moet u echter asynchrone methoden gebruiken om uw app op een schaalbare en responsieve manier te laten werken. U kunt bijvoorbeeld CreateIndexAsync gebruiken in plaats van CreateIndex.

De structuren definiëren

U hebt twee helperklassen gemaakt, Hotel.java en Address.java, om de structuur van een hoteldocument en het bijbehorende adres te definiëren. De klasse Hotel bevat velden voor een hotel-id, naam, beschrijving, categorie, tags, parkeren, renovatiedatum, beoordeling en adres. De klasse Adres bevat velden voor straatadres, plaats, provincie, postcode en land/regio.

In de clientbibliotheek van Azure.Search.Documents kunt u velddefinities stroomlijnen met behulp van de velden SearchableField en SimpleField.

  • SimpleField kan elk gegevenstype zijn, is altijd niet doorzoekbaar (genegeerd voor zoekquery's in volledige tekst) en kan worden opgehaald (niet verborgen). Andere kenmerken zijn standaard uitgeschakeld, maar kunnen wel worden ingeschakeld. U kunt een SimpleField gebruiken voor document-id's of velden die alleen worden gebruikt in filters, facetten of scoreprofielen. Als dit het geval is, moet u alle kenmerken toepassen die nodig zijn voor het scenario, zoals IsKey = true voor een document-id.
  • SearchableField moet een tekenreeks zijn die altijd kan worden doorzocht en opgehaald. Andere kenmerken zijn standaard uitgeschakeld, maar kunnen wel worden ingeschakeld. Omdat dit veldtype kan worden doorzocht, worden synoniemen en het volledige gamma van analyse-eigenschappen ondersteund.

Ongeacht of u de basis-API van SearchField of een van de hulpmodellen gebruikt, u moet filter-, facet- en sorteerkenmerken expliciet inschakelen. Bijvoorbeeld, isFilterableisSortableen isFacetable moet expliciet worden toegeschreven, zoals wordt weergegeven in de vorige steekproef.

De zoekindex maken

In App.javamaakt u een SearchIndex object in de main methode en roept u de createOrUpdateIndex methode aan om de index in uw zoekservice te maken. De index bevat ook een SearchSuggester functie om automatisch aanvullen in te schakelen voor de opgegeven velden.

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

Documenten laden

Azure AI Search zoekt naar inhoud die is opgeslagen in de service. In deze stap laadt u JSON-documenten die voldoen aan de hotelindex die u hebt gemaakt.

In Azure AI Search zijn zoekdocumenten gegevensstructuren die zowel invoer zijn voor het indexeren als uitvoeren van query's. Als u de documenten hebt verkregen via een externe gegevensbron, bestaat de documentinvoer mogelijk uit rijen in een database, blobs in Blob Storage of JSON-documenten op een schijf. In dit voorbeeld nemen we de korte route en gaan we JSON-documenten voor vier hotels in de code zelf insluiten.

Bij het uploaden van documenten moet u een IndexDocumentsBatch-object gebruiken. Een IndexDocumentsBatch object bevat een verzameling IndexActions, die elk een document en een eigenschap bevatten die Azure AI Search vertelt welke actie moet worden uitgevoerd (uploaden, samenvoegen, verwijderen en samenvoegen).

In App.javamaakt u documenten en indexacties en geeft u ze door aan IndexDocumentsBatch. De volgende documenten voldoen aan de index hotels-quickstart, zoals gedefinieerd door de hotelklasse.

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

    var hotel = new Hotel();
    hotel.hotelId = "1";
    hotel.hotelName = "Stay-Kay City Hotel";
    hotel.description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
    hotel.category = "Boutique";
    hotel.tags = new String[] { "view", "air conditioning", "concierge" };
    hotel.parkingIncluded = false;
    hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2022, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
    hotel.rating = 3.6;
    hotel.address = new Address();
    hotel.address.streetAddress = "677 5th Ave";
    hotel.address.city = "New York";
    hotel.address.stateProvince = "NY";
    hotel.address.postalCode = "10022";
    hotel.address.country = "USA";
    hotelList.add(hotel);
    
    // REDACTED FOR BREVITY

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

Nadat u het IndexDocumentsBatch object hebt geïnitialiseerd, kunt u het naar de index verzenden door indexDocuments.

U laadt documenten met SearchClient in main(), maar voor de bewerking zijn ook beheerdersrechten vereist voor de service, die doorgaans is gekoppeld aan SearchIndexClient. Een manier om deze bewerking in te stellen, is door SearchClient door SearchIndexClient te halen (searchIndexClient in dit voorbeeld).

uploadDocuments(searchClient);

Omdat we een console-app hebben waarmee alle opdrachten opeenvolgend worden uitgevoerd, voegen we een wachttijd van 2 seconden toe tussen indexering en query's.

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

De vertraging van 2 seconden compenseert de indexering (die asynchroon is), zodat alle documenten kunnen worden geïndexeerd voordat de query's worden uitgevoerd. Codering in een vertraging is doorgaans alleen nodig in demo's, testen en voorbeeldtoepassingen.

Een index doorzoeken

U kunt queryresultaten ophalen zodra het eerste document wordt geïndexeerd, maar wacht met het daadwerkelijk testen van uw index totdat alle documenten zijn geïndexeerd.

In deze sectie worden twee onderdelen van functionaliteit toegevoegd: querylogica en resultaten. Gebruik voor query's de methode Search. Deze methode gebruikt zoektekst (de querytekenreeks) en andere opties.

In App.javade WriteDocuments methode worden zoekresultaten naar de console afgedrukt.

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

Queryvoorbeeld 1

De RunQueries methode voert query's uit en retourneert resultaten. Resultaten zijn Hotel-objecten. In dit voorbeeld ziet u de handtekening en de eerste query van de methode. Deze query demonstreert de Select parameter waarmee u het resultaat kunt opstellen met behulp van geselecteerde velden uit het document.

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

Queryvoorbeeld 2

In de tweede query zoekt u op een term, voegt u een filter toe waarmee documenten worden geselecteerd waarin Waardering groter is dan 4 en vervolgens in aflopende volgorde op Classificatie sorteren. Filter is een Booleaanse expressie die wordt geëvalueerd op isFilterable velden in een index. Filterquery's bevatten waarden of sluiten ze uit. Er is dus geen relevantiescore gekoppeld aan een filterquery.

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

Queryvoorbeeld 3

De derde query laat zien searchFields, dat wordt gebruikt om een zoekbewerking voor volledige tekst te bepalen voor specifieke velden.

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

Queryvoorbeeld 4

De vierde query laat zien facets, die kan worden gebruikt om een facetnavigatiestructuur te structuren.

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

Queryvoorbeeld 5

In de vijfde query retourneert u een specifiek document.

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

Queryvoorbeeld 6

De laatste query toont de syntaxis voor automatisch aanvullen, waarbij een gedeeltelijke gebruikersinvoer van s wordt gesimsimeerd die wordt omgezet in twee mogelijke overeenkomsten in de sourceFields gekoppelde aan de suggestie die u in de index hebt gedefinieerd.

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

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

Samenvatting van query's

De vorige query's tonen meerdere manieren om termen in een query te koppelen: zoekopdracht in volledige tekst, filters en automatisch aanvullen.

Zoekopdrachten en filters voor volledige tekst worden uitgevoerd met behulp van de zoekmethode SearchClient.search . Een zoekquery kan worden doorgegeven in de searchText tekenreeks, terwijl een filterexpressie kan worden doorgegeven in de filter eigenschap van de klasse SearchOptions . Als u wilt filteren zonder te zoeken, geeft u '*' door voor de searchText parameter van de search methode. Als u wilt zoeken zonder te filteren, laat u de filter eigenschap uitgeschakeld of geeft u een SearchOptions instantie helemaal niet door.

In deze quickstart gebruikt u de clientbibliotheek Azure.Search.Documents om een zoekindex te maken, laden en er query's op uit te voeren met voorbeeldgegevens voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Vereisten voor Microsoft Entra-id

Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:

Resourcegegevens ophalen

U moet de volgende informatie ophalen om uw toepassing te verifiëren met uw Azure AI-Search-service:

Naam van de variabele Weergegeven als
SEARCH_API_ENDPOINT Deze waarde vindt u in Azure Portal. Selecteer uw zoekservice en selecteer vervolgens in het linkermenu Overzicht. De URL-waarde onder Essentials is het eindpunt dat u nodig hebt. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

Meer informatie over sleutelloze verificatie en het instellen van omgevingsvariabelen.

Instellingen

  1. Maak een nieuwe map full-text-quickstart die de toepassing bevat en open Visual Studio Code in die map met de volgende opdracht:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Maak de package.json opdracht met de volgende opdracht:

    npm init -y
    
  3. Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor JavaScript met:

    npm install @azure/search-documents
    
  4. Installeer voor de aanbevolen verificatie zonder wachtwoord de Azure Identity-clientbibliotheek met:

    npm install @azure/identity
    

Een zoekindex maken, laden en er query's op uitvoeren

In de vorige sectie voor het instellen hebt u de Azure AI Search-clientbibliotheek en andere afhankelijkheden geïnstalleerd.

In deze sectie voegt u code toe om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U voert het programma uit om de resultaten in de console te zien. Zie de uitleg van de codesectie voor een gedetailleerde uitleg van de code .

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
  1. Maak een nieuw bestand met de naam index.js en plak de volgende code in 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 palace", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
        // Query 4
        console.log('Query #4 - limit searchFields and use facets:');
        searchOptions = {
            facets: ["Category"],
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
        searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
        // Query 5
        console.log('Query #5 - Lookup document:');
        let documentResult = await searchClient.getDocument('3');
        console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);
        console.log();
    }
    function sleep(ms) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    main().catch((err) => {
        console.error("The sample encountered an error:", err);
    });
    
  2. Maak een bestand met de naam hotels.json en plak de volgende code in hotels.json:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Stay-Kay City Hotel",
                "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                "Category": "Boutique",
                "Tags": ["view", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "2022-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "HotelId": "2",
                "HotelName": "Old Century Hotel",
                "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "2019-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Gastronomic Landscape Hotel",
                "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Category": "Suite",
                "Tags": ["restaurant", "bar", "continental breakfast"],
                "ParkingIncluded": "true",
                "LastRenovationDate": "2015-09-20T00:00:00Z",
                "Rating": 4.8,
                "Address": {
                    "StreetAddress": "3393 Peachtree Rd",
                    "City": "Atlanta",
                    "StateProvince": "GA",
                    "PostalCode": "30326"
                }
            },
            {
                "HotelId": "4",
                "HotelName": "Sublime Palace Hotel",
                "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "air conditioning"],
                "ParkingIncluded": true,
                "LastRenovationDate": "2020-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. Maak een bestand met de naam hotels_quickstart_index.json en plak de volgende code in 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": "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. Meld u aan bij Azure met de volgende opdracht:

    az login
    
  5. Voer de JavaScript-code uit met de volgende opdracht:

    node index.js
    

Uitleg van de code

Index maken

Het hotels_quickstart_index.json-bestand definieert hoe Azure AI Search werkt met de documenten die u in de volgende stap laadt. Elk veld wordt geïdentificeerd door een name en heeft een opgegeven type. Elk veld heeft ook een reeks indexkenmerken die aangeven of Azure AI Search kan zoeken, filteren, sorteren en facet op het veld. De meeste velden zijn eenvoudige gegevenstypen, maar een aantal, zoals AddressType, is van een complex type waarmee u uitgebreide gegevensstructuren in uw index kunt maken. Meer informatie over ondersteunde gegevenstypen en indexkenmerken die worden beschreven in Create Index (REST).

Als u de indexdefinitie hebt geïmplementeerd, wilt u hotels_quickstart_index. json boven in het bestand index.js importeren, zodat de hoofdfunctie de indexdefinitie kan openen.

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

In de hoofdfunctie maken we vervolgens een SearchIndexClient, die wordt gebruikt voor het maken en beheren van indexen voor Azure AI Search.

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

De index moet worden verwijderd als deze al bestaat. Deze bewerking is een veelvoorkomende procedure voor test-/democode.

Dit doet u door een eenvoudige functie te definiëren die probeert om de index te verwijderen.

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

Als u de functie wilt uitvoeren, halen we de indexnaam op uit de indexdefinitie en geven we de indexName door met de indexClient aan de functie deleteIndexIfExists().

const indexName = indexDefinition["name"];

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

Daarna kunt u de index maken met behulp van de methode createIndex().

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

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

Documenten laden

In Azure AI Search zijn documenten gegevensstructuren die zowel invoer zijn voor het indexeren als uitvoeren van query's. U kunt dergelijke gegevens naar de index pushen of een Indexeerfunctie gebruiken. In dit geval pushen we de documenten programmatisch naar de index.

De documentinvoer bestaat mogelijk uit rijen in een database, blobs in Blob Storage of, zoals in dit voorbeeld, JSON-documenten op een schijf. Net als bij wat we hebben gedaan met de indexDefinition, moeten we ook importeren hotels.json bovenaan index.js , zodat de gegevens kunnen worden geopend in onze hoofdfunctie.

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

Als u gegevens in de zoekindex wilt indexeren, moet u nu een SearchClient maken. Terwijl de SearchIndexClient wordt gebruikt voor het maken en beheren van een index, wordt de SearchClient gebruikt voor het uploaden van documenten en het uitvoeren van query's op de index.

Er zijn twee manieren om een SearchClient maken. De eerste optie is het maken van een geheel nieuwe SearchClient:

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

U kunt ook de methode getSearchClient() van de SearchIndexClient gebruiken om de SearchClient te maken:

const searchClient = indexClient.getSearchClient(indexName);

Nu de client is gedefinieerd, uploadt u de documenten in de zoekindex. In dit geval gebruiken we de mergeOrUploadDocuments() methode, waarmee de documenten worden geüpload of samengevoegd met een bestaand document als er al een document met dezelfde sleutel bestaat.

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

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

Een index doorzoeken

Als er een index is gemaakt en documenten zijn geüpload, bent u klaar om query's naar de index te verzenden. In deze sectie verzenden we vijf verschillende query's naar de zoekindex om verschillende onderdelen van de queryfunctionaliteit te demonstreren die voor u beschikbaar zijn.

De query's worden als volgt geschreven in een sendQueries() functie die we in de hoofdfunctie aanroepen:

await sendQueries(searchClient);

Query's worden verzonden met behulp van de methode search() van searchClient. De eerste parameter is de zoektekst en de tweede parameter specificeert zoekopties.

Queryvoorbeeld 1

De eerste query zoekt *, wat gelijk is aan ‘zoeken in alle’ en selecteert drie van de velden in de index. Het is een best practice om alleen de velden te select die u nodig hebt, omdat het ophalen van overbodige gegevens een latentie kan veroorzaken bij uw query's.

De searchOptions voor deze query is includeTotalCount ook ingesteld op true, waarmee het aantal gevonden overeenkomende resultaten wordt geretourneerd.

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 resterende query's die hieronder worden beschreven, moeten ook worden toegevoegd aan de functie sendQueries(). Ze zijn hier gescheiden voor leesbaarheid.

Queryvoorbeeld 2

In de volgende query geven we de zoekterm "wifi" op en nemen we ook een filter op om alleen resultaten te retourneren waarvan de status gelijk is aan 'FL'. Resultaten worden ook gerangschikt op de Ratingvan het hotel.

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

Queryvoorbeeld 3

Vervolgens kan de zoekopdracht worden beperkt tot één doorzoekbaar veld met behulp van de parameter searchFields. Deze methode is een uitstekende optie om uw query efficiënter te maken als u weet dat u alleen geïnteresseerd bent in overeenkomsten in bepaalde velden.

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

Queryvoorbeeld 4

Een andere veelgebruikte optie die in een query moet worden opgenomen, is facets. Met facetten kunt u filters maken op uw gebruikersinterface, zodat gebruikers eenvoudig kunnen zien welke waarden ze kunnen filteren.

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

Queryvoorbeeld 5

De laatste query maakt gebruik van de methode getDocument() van de searchClient. Zo kunt u een document efficiënt ophalen met de bijbehorende sleutel.

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

Samenvatting van query's

De vorige query's tonen meerdere manieren om termen in een query te koppelen: zoekopdracht in volledige tekst, filters en automatisch aanvullen.

Zoekopdrachten en filters voor volledige tekst worden uitgevoerd met behulp van de searchClient.search methode. Een zoekquery kan worden doorgegeven in de searchText tekenreeks, terwijl een filterexpressie kan worden doorgegeven in de filter eigenschap van de SearchOptions klasse. Als u wilt filteren zonder te zoeken, geeft u '*' door voor de searchText parameter van de search methode. Als u wilt zoeken zonder te filteren, laat u de filter eigenschap uitgeschakeld of geeft u een SearchOptions instantie helemaal niet door.

In deze quickstart gebruikt u PowerShell en de REST API's van Azure AI Search om een zoekindex te maken, laden en er query's op uit te voeren voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Toegang configureren

U kunt verbinding maken met uw Azure AI Search-service met behulp van API-sleutels of Microsoft Entra-id met roltoewijzingen. Sleutels zijn gemakkelijker te beginnen, maar rollen zijn veiliger.

De aanbevolen op rollen gebaseerde toegang configureren:

  1. Meld u aan bij Azure Portal en selecteer uw zoekservice.

  2. In het linkerdeelvenster, selecteer Instellingen>Sleutels.

  3. Selecteer Onder API-toegangsbeheer beide.

    Met deze optie kunt u zowel sleutelgebaseerde als sleutelvrije verificatie inschakelen. Nadat u rollen hebt toegewezen, kunt u terugkeren naar deze stap en op rollen gebaseerd toegangsbeheer selecteren.

  4. Selecteer toegangsbeheer (IAM) in het linkerdeelvenster.

  5. Selecteer Toevoegen>Roltoewijzing toevoegen.

  6. Wijs de rollen Inzender voor zoekservice en Inzender voor zoekindexgegevens toe aan uw gebruikersaccount.

Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.

Eindpunt ophalen

In de volgende sectie geeft u het volgende eindpunt op om een verbinding tot stand te brengen met uw Azure AI Search-service. Bij deze stappen wordt ervan uitgegaan dat u op rollen gebaseerde toegang hebt geconfigureerd.

Volg deze stappen om uw service-eindpunt te verkrijgen:

  1. Meld u aan bij Azure Portal en selecteer uw zoekservice.

  2. Selecteer Overzicht in het linkerdeelvenster.

  3. Noteer de URL, die vergelijkbaar moet zijn met https://my-service.search.windows.net.

Voordat u REST API-aanroepen naar uw Azure AI Search-service kunt uitvoeren, moet u zich verifiëren en verbinding maken met de service. U voert de volgende stappen uit in PowerShell, die ondersteuning biedt voor de Azure CLI-opdrachten die in stap twee en drie worden gebruikt.

Verbinding maken met uw zoekservice:

  1. Open PowerShell op uw lokale systeem.

  2. Meld u aan bij uw Azure-abonnement. Als u meerdere abonnementen hebt, selecteert u het abonnement dat uw zoekservice bevat.

    az login
    
  3. Maak een $token object om uw toegangstoken op te slaan.

    $token = az account get-access-token --resource https://search.azure.com/ --query accessToken --output tsv
    
  4. Maak een $headers object om uw token en inhoudstype op te slaan.

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

    U hoeft de header slechts eenmaal per sessie in te stellen, maar u moet deze aan elke aanvraag toevoegen.

  5. Maak een $url object dat is gericht op de verzameling indexen in uw zoekservice. Vervang <YOUR-SEARCH-SERVICE> door de waarde die u hebt verkregen in het eindpunt Ophalen.

    $url = "<YOUR-SEARCH-SERVICE>/indexes?api-version=2024-07-01&`$select=name"
    
  6. Voer Invoke-RestMethod deze opdracht uit om een GET-aanvraag naar uw zoekservice te verzenden. Voeg ConvertTo-Json toe om reacties van de service weer te geven.

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

    Als uw service leeg is en geen indexen bevat, is het antwoord vergelijkbaar met het volgende voorbeeld. Anders ziet u een JSON-weergave van indexdefinities.

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

Een zoekindex maken

Voordat u inhoud toevoegt aan Azure AI Search, moet u een index maken om te definiëren hoe de inhoud wordt opgeslagen en gestructureerd. Een index is conceptueel vergelijkbaar met een tabel in een relationele database, maar is speciaal ontworpen voor zoekbewerkingen, zoals zoeken in volledige tekst.

Voer de volgende opdrachten uit in dezelfde PowerShell-sessie die u in de vorige sectie hebt gestart.

Een index maken:

  1. Maak een $body object om het indexschema te definiëren.

    $body = @"
    {
        "name": "hotels-quickstart",  
        "fields": [
            {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true},
            {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false},
            {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"},
            {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
            {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true},
            {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true},
            {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true},
            {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true},
            {"name": "Address", "type": "Edm.ComplexType", 
                "fields": [
                {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true},
                {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}
            ]
         }
      ]
    }
    "@
    
  2. Werk het $url object bij om de nieuwe index te targeten. Vervang <YOUR-SEARCH-SERVICE> door de waarde die u hebt verkregen in het eindpunt Ophalen.

    $url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart?api-version=2024-07-01"
    
  3. Voer Invoke-RestMethod deze opdracht uit om de index in uw zoekservice te maken.

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

    Het antwoord moet de JSON-weergave van het indexschema bevatten.

Over de aanvraag voor het maken van een index

In deze quickstart worden Indexen - Create (REST API) aangeroepen om een zoekindex met de naam hotels-quickstart en de bijbehorende fysieke gegevensstructuren in uw zoekservice te bouwen.

Binnen het indexschema definieert de fields verzameling de structuur van hoteldocumenten. Elk veld heeft een name, gegevens typeen kenmerken die het gedrag bepalen tijdens het indexeren en uitvoeren van query's. Het HotelId veld wordt gemarkeerd als de sleutel, waarvoor Azure AI Search elk document in een index uniek moet identificeren.

Belangrijke punten over het indexschema:

  • Gebruik tekenreeksvelden (Edm.String) om numerieke gegevens doorzoekbaar te maken in volledige tekst. Andere ondersteunde gegevenstypen, zoals Edm.Int32, zijn filterbaar, sorteerbaar, facetabel en ophaalbaar, maar kunnen niet worden doorzocht.

  • De meeste velden zijn eenvoudige gegevenstypen, maar u kunt complexe typen definiëren om geneste gegevens weer te geven, zoals het Address veld.

  • Veldkenmerken bepalen toegestane acties. De REST API's staan standaard veel acties toe. Bijvoorbeeld, alle tekenreeksen kunnen worden doorzocht en opgehaald. Met de REST API's kunt u mogelijk alleen kenmerken gebruiken als u een gedrag wilt uitschakelen.

De index laden

Nieuw gemaakte indexen zijn leeg. Als u een index wilt vullen en doorzoekbaar wilt maken, moet u JSON-documenten uploaden die voldoen aan het indexschema.

In Azure AI Search fungeren documenten als invoer voor indexering en uitvoer voor query's. Om het eenvoudig te maken, geeft deze quickstart voorbeelddocumenten van hotels in de vorm van inline JSON. In productiescenario's wordt inhoud echter vaak opgehaald uit verbonden gegevensbronnen en omgezet in JSON met behulp van indexeerfuncties.

Documenten uploaden naar uw index:

  1. Maak een $body object voor het opslaan van de JSON-nettolading van vier voorbeelddocumenten.

    $body = @"
        {
            "value": [
            {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
            "Category": "Boutique",
            "Tags": [ "view", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2022-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "2",
            "HotelName": "Old Century Hotel",
            "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
            "Category": "Boutique",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2019-02-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "3",
            "HotelName": "Gastronomic Landscape Hotel",
            "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
            "Category": "Suite",
            "Tags": [ "restaurant", "bar", "continental breakfast" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.80,
            "Address": 
                {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "4",
            "HotelName": "Sublime Palace Hotel",
            "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
            "Category": "Boutique",
            "Tags": [ "concierge", "view", "air conditioning" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2020-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
                {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
                }
            }
          ]
        }
    "@
    
  2. Werk het $url object bij om het indexeringseindpunt te targeten. Vervang <YOUR-SEARCH-SERVICE> door de waarde die u hebt verkregen in het eindpunt Ophalen.

    $url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs/index?api-version=2024-07-01"
    
  3. Voer Invoke-RestMethod deze opdracht uit om de uploadaanvraag naar uw zoekservice te verzenden.

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

    Het antwoord moet de sleutel en status van elk geüpload document bevatten.

Over de uploadaanvraag

In deze quickstart wordt Documenten - Index (REST API) aangeroepen om vier voorbeeldhoteldocumenten aan uw index toe te voegen. In vergelijking met de vorige aanvraag wordt de URI uitgebreid met de docs verzameling en index bewerking.

Elk document in de value matrix vertegenwoordigt een hotel en bevat velden die overeenkomen met het indexschema. De @search.action parameter geeft de bewerking op die moet worden uitgevoerd voor elk document. In ons voorbeeld wordt het document met upload toegevoegd als het niet bestaat, of bijgewerkt als het wel bestaat.

Query's uitvoeren op de index

Nu documenten in uw index zijn geladen, kunt u zoeken in volledige tekst gebruiken om specifieke termen of woordgroepen in hun velden te vinden.

Een volledige-tekstquery uitvoeren op uw index:

  1. Werk het $url object bij om zoekparameters op te geven. Vervang <YOUR-SEARCH-SERVICE> door de waarde die u hebt verkregen in het eindpunt Ophalen.

    $url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=attached restaurant&searchFields=Description,Tags&$select=HotelId,HotelName,Tags,Description&$count=true'
    
  2. Voer Invoke-RestMethod uit om de query naar uw zoekservice te verzenden.

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

    Het antwoord moet vergelijkbaar zijn met het volgende voorbeeld, waarin één overeenkomend hoteldocument, de relevantiescore en de geselecteerde velden worden weergegeven.

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

Over de queryaanvraag

Deze quickstart roept Documenten - Search Post (REST API) aan om hoteldocumenten te vinden die voldoen aan uw zoekcriteria. De URI is nog steeds gericht op de docs verzameling, maar bevat de index bewerking niet meer.

Zoekaanvragen voor volledige tekst bevatten altijd een search parameter die de querytekst bevat. De querytekst kan een of meer termen, woordgroepen of operatoren bevatten. Daarnaast searchkunt u andere parameters opgeven om het zoekgedrag en de resultaten te verfijnen.

Onze query zoekt naar de termen 'bijgevoegd restaurant' in de Description velden Tags van elk hoteldocument. De $select parameter beperkt de velden die worden geretourneerd in het antwoord op HotelId, HotelNameen TagsDescription. De $count parameter vraagt het totale aantal overeenkomende documenten aan.

Andere queryvoorbeelden

Voer de volgende opdrachten uit om de querysyntaxis te verkennen. U kunt zoekopdrachten in tekenreeksen uitvoeren, expressies gebruiken $filter , resultatensets beperken, specifieke velden selecteren en meer. Vergeet niet om <YOUR-SEARCH-SERVICE> te vervangen door de waarde die u hebt verkregen in Get endpoint.

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

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

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

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

In deze quickstart gebruikt u de clientbibliotheek Azure.Search.Documents om een zoekindex te maken, laden en er query's op uit te voeren met voorbeeldgegevens voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt een voltooid notebook downloaden en uitvoeren.

Vereisten

Vereisten voor Microsoft Entra-id

Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:

Resourcegegevens ophalen

U moet de volgende informatie ophalen om uw toepassing te verifiëren met uw Azure AI-Search-service:

Naam van de variabele Weergegeven als
SEARCH_API_ENDPOINT Deze waarde vindt u in Azure Portal. Selecteer uw zoekservice en selecteer vervolgens in het linkermenu Overzicht. De URL-waarde onder Essentials is het eindpunt dat u nodig hebt. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

Meer informatie over sleutelloze verificatie en het instellen van omgevingsvariabelen.

Uw omgeving instellen

U voert de voorbeeldcode uit in een Jupyter-notebook. U moet dus uw omgeving instellen om Jupyter-notebooks uit te voeren.

  1. Download of kopieer het voorbeeldnotebook vanuit GitHub.

  2. Open het notebook in Visual Studio Code.

  3. Maak een nieuwe Python-omgeving om de pakketten te installeren die u nodig hebt voor deze zelfstudie.

    Belangrijk

    Installeer geen pakketten in uw globale Python-installatie. U moet altijd een virtuele of conda-omgeving gebruiken bij het installeren van Python-pakketten, anders kunt u uw globale installatie van Python verbreken.

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

    Het kan even duren voordat het is ingesteld. Als u problemen ondervindt, raadpleegt u Python-omgevingen in VS Code.

  4. Installeer Jupyter-notebooks en de IPython Kernel voor Jupyter-notebooks als u deze nog niet hebt.

    pip install jupyter
    pip install ipykernel
    python -m ipykernel install --user --name=.venv
    
  5. Selecteer de notebook-kernel.

    1. Selecteer Kernel in de rechterbovenhoek van het notitieblok.
    2. Als u deze in de lijst ziet .venv , selecteert u deze. Als u deze niet ziet, selecteert u Een andere Kernel>Python-omgevingen>.venv selecteren.

Een zoekindex maken, laden en er query's op uitvoeren

In deze sectie voegt u code toe om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U voert het programma uit om de resultaten in de console te zien. Zie de uitleg van de codesectie voor een gedetailleerde uitleg van de code .

  1. Zorg ervoor dat het notebook is geopend in de .venv kernel, zoals beschreven in de vorige sectie.

  2. Voer de eerste codecel uit om de vereiste pakketten te installeren, inclusief azure-search-documents.

    ! pip install azure-search-documents==11.6.0b1 --quiet
    ! pip install azure-identity --quiet
    ! pip install python-dotenv --quiet
    
  3. Vervang de inhoud van de tweede codecel door de volgende code, afhankelijk van uw verificatiemethode.

    Notitie

    De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

    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. Verwijder de volgende twee regels uit de cel Een indexcode maken. Referenties zijn al ingesteld in de vorige codecel.

    from azure.core.credentials import AzureKeyCredential
    credential = AzureKeyCredential(search_api_key)
    
  5. Voer de cel Een indexcode maken uit om een zoekindex te maken.

  6. Voer de resterende codecellen opeenvolgend uit om documenten te laden en query's uit te voeren.

Uitleg van de code

Een index maken

SearchIndexClient wordt gebruikt voor het maken en beheren van indexen voor Azure AI Search. Elk veld wordt geïdentificeerd door een name en heeft een opgegeven type.

Elk veld heeft ook een reeks indexkenmerken die aangeven of Azure AI Search kan zoeken, filteren, sorteren en facet op het veld. De meeste velden zijn eenvoudige gegevenstypen, maar een aantal, zoals AddressType, is van een complex type waarmee u uitgebreide gegevensstructuren in uw index kunt maken. Meer informatie over ondersteunde gegevenstypen en indexkenmerken die worden beschreven in Create Index (REST).

Een nettolading van documenten maken en documenten uploaden

Gebruik een indexactie voor het bewerkingstype, zoals uploaden of samenvoegen en uploaden. Documenten zijn afkomstig van het Voorbeeld HotelsData op GitHub.

Een index doorzoeken

U kunt queryresultaten ophalen zodra het eerste document wordt geïndexeerd, maar wacht met het daadwerkelijk testen van uw index totdat alle documenten zijn geïndexeerd.

Gebruik de zoekmethode van de klasse search.client.

De voorbeeldquery's in het notebook zijn:

  • Basisquery: voert een lege zoekopdracht (search=*) uit, retourneert een ongerankeerde lijst (zoekscore = 1,0) van willekeurige documenten. Omdat er geen criteria zijn, worden alle documenten opgenomen in de resultaten.
  • Termquery: voegt hele termen toe aan de zoekexpressie ('wifi'). Met deze query wordt opgegeven dat de resultaten alleen die velden bevatten in de select-instructie. Het beperken van de velden die worden geretourneerd, minimaliseert de hoeveelheid gegevens die via de kabel wordt verzonden en vermindert de zoeklatentie.
  • Gefilterde query: Voeg een filterexpressie toe, waarbij alleen hotels met een classificatie groter dan vier worden geretourneerd, gesorteerd in aflopende volgorde.
  • Bereikveld: Toevoegen search_fields aan bereikquery-uitvoering aan specifieke velden.
  • Facetten: facetten genereren voor positieve overeenkomsten die in de zoekresultaten worden gevonden. Er zijn geen nulovereenkomsten. Als zoekresultaten de term wifi niet bevatten, wordt wifi niet weergegeven in de facetnavigatiestructuur.
  • Een document opzoeken: een document retourneren op basis van de sleutel. Deze bewerking is handig als u drill through wilt opgeven wanneer een gebruiker een item in een zoekresultaat selecteert.
  • Automatisch aanvullen: geef potentiële overeenkomsten op als de gebruiker in het zoekvak typt. Automatisch aanvullen maakt gebruik van een suggestie (sg) om te weten welke velden mogelijke overeenkomsten bevatten voor suggestieaanvragen. In deze quickstart zijn Tagsdeze velden , . Address/CityAddress/Country Als u automatisch aanvullen wilt simuleren, geeft u de letters sa door als een gedeeltelijke tekenreeks. Met de methode voor automatisch aanvullen van SearchClient worden mogelijke overeenkomende termen geretourneerd.

De index verwijderen

Als u klaar bent met deze index, kunt u deze verwijderen door de codecel Opschonen uit te voeren. Als u onnodige indexen verwijdert, wordt ruimte vrijgemaakt voor het doorlopen van meer quickstarts en zelfstudies.

In deze quickstart gebruikt u de REST API's van Azure AI Search om een zoekindex te maken, te laden en te doorzoeken voor volledige-tekstzoekopdrachten. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Toegang configureren

U kunt verbinding maken met uw Azure AI Search-service met behulp van API-sleutels of Microsoft Entra-id met roltoewijzingen. Sleutels zijn gemakkelijker te beginnen, maar rollen zijn veiliger.

De aanbevolen op rollen gebaseerde toegang configureren:

  1. Meld u aan bij Azure Portal en selecteer uw zoekservice.

  2. In het linkerdeelvenster, selecteer Instellingen>Sleutels.

  3. Selecteer Onder API-toegangsbeheer beide.

    Met deze optie kunt u zowel sleutelgebaseerde als sleutelvrije verificatie inschakelen. Nadat u rollen hebt toegewezen, kunt u terugkeren naar deze stap en op rollen gebaseerd toegangsbeheer selecteren.

  4. Selecteer toegangsbeheer (IAM) in het linkerdeelvenster.

  5. Selecteer Toevoegen>Roltoewijzing toevoegen.

  6. Wijs de rollen Inzender voor zoekservice en Inzender voor zoekindexgegevens toe aan uw gebruikersaccount.

Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.

Eindpunt en token ophalen

In de volgende sectie geeft u het volgende eindpunt en token op om een verbinding tot stand te brengen met uw Azure AI Search-service. Bij deze stappen wordt ervan uitgegaan dat u op rollen gebaseerde toegang hebt geconfigureerd.

Ga als volgende te werk om uw service-eindpunt en -token op te halen:

  1. Meld u aan bij Azure Portal en selecteer uw zoekservice.

  2. Selecteer Overzicht in het linkerdeelvenster.

  3. Noteer de URL, die vergelijkbaar moet zijn met https://my-service.search.windows.net.

  4. Open een terminal op uw lokale systeem.

  5. Meld u aan bij uw Azure-abonnement. Als u meerdere abonnementen hebt, selecteert u het abonnement dat uw zoekservice bevat.

    az login
    
  6. Noteer uw Microsoft Entra-token.

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

Stel uw bestand in

Voordat u REST API-aanroepen naar uw Azure AI Search-service kunt maken, moet u een bestand maken om uw service-eindpunt, verificatietoken en uiteindelijke aanvragen op te slaan. De REST Client-extensie in Visual Studio Code ondersteunt deze taak.

Uw aanvraagbestand instellen:

  1. Open Visual Studio Code op uw lokale systeem.

  2. Maak een .rest of .http bestand.

  3. Plak de volgende tijdelijke aanduidingen en verzoek in het bestand.

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @token = PUT-YOUR-PERSONAL-IDENTITY-TOKEN-HERE
    
    ### List existing indexes by name
    GET {{baseUrl}}/indexes?api-version=2024-07-01  HTTP/1.1
        Authorization: Bearer {{token}}
    
  4. Vervang de @baseUrl en @token tijdelijke aanduidingen met de waarden die u hebt verkregen in Eindpunt en token ophalen. Voer geen aanhalingstekens in.

  5. Selecteer onder ### List existing indexes by nameVerzenden aanvraag.

    Er moet een antwoord worden weergegeven in een aangrenzend deelvenster. Als u bestaande indexen hebt, worden deze weergegeven. Anders is de lijst leeg. Als de HTTP-code is 200 OK, bent u klaar voor de volgende stappen.

    Schermopname van een REST-client die is geconfigureerd voor een zoekserviceaanvraag.

Een zoekindex maken

Voordat u inhoud toevoegt aan Azure AI Search, moet u een index maken om te definiëren hoe de inhoud wordt opgeslagen en gestructureerd. Een index is conceptueel vergelijkbaar met een tabel in een relationele database, maar is speciaal ontworpen voor zoekbewerkingen, zoals zoeken in volledige tekst.

Een index maken:

  1. Plak de volgende aanvraag in uw bestand.

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

    U ontvangt een HTTP/1.1 201 Created antwoord waarvan de hoofdtekst de JSON-weergave van het indexschema bevat.

Over de aanvraag voor het maken van een index

In deze quickstart worden Indexen - Create (REST API) aangeroepen om een zoekindex met de naam hotels-quickstart en de bijbehorende fysieke gegevensstructuren in uw zoekservice te bouwen.

Binnen het indexschema definieert de fields verzameling de structuur van hoteldocumenten. Elk veld heeft een name, gegevens typeen kenmerken die het gedrag bepalen tijdens het indexeren en uitvoeren van query's. Het HotelId veld wordt gemarkeerd als de sleutel, waarvoor Azure AI Search elk document in een index uniek moet identificeren.

Belangrijke punten over het indexschema:

  • Gebruik tekenreeksvelden (Edm.String) om numerieke gegevens doorzoekbaar te maken in volledige tekst. Andere ondersteunde gegevenstypen, zoals Edm.Int32, zijn filterbaar, sorteerbaar, facetabel en ophaalbaar, maar kunnen niet worden doorzocht.

  • De meeste velden zijn eenvoudige gegevenstypen, maar u kunt complexe typen definiëren om geneste gegevens weer te geven, zoals het Address veld.

  • Veldkenmerken bepalen toegestane acties. De REST API's staan standaard veel acties toe. Bijvoorbeeld, alle tekenreeksen kunnen worden doorzocht en opgehaald. Met de REST API's kunt u mogelijk alleen kenmerken gebruiken als u een gedrag wilt uitschakelen.

De index laden

Nieuw gemaakte indexen zijn leeg. Als u een index wilt vullen en doorzoekbaar wilt maken, moet u JSON-documenten uploaden die voldoen aan het indexschema.

In Azure AI Search fungeren documenten als invoer voor indexering en uitvoer voor query's. Om het eenvoudig te maken, geeft deze quickstart voorbeelddocumenten van hotels in de vorm van inline JSON. In productiescenario's wordt inhoud echter vaak opgehaald uit verbonden gegevensbronnen en omgezet in JSON met behulp van indexeerfuncties.

Documenten uploaden naar uw index:

  1. Plak de volgende aanvraag in uw bestand.

    ### Upload documents
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version=2024-07-01  HTTP/1.1
        Content-Type: application/json
        Authorization: Bearer {{token}}
    
        {
            "value": [
            {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
            "Category": "Boutique",
            "Tags": [ "view", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2022-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "2",
            "HotelName": "Old Century Hotel",
            "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
             "Category": "Boutique",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2019-02-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "3",
            "HotelName": "Gastronomic Landscape Hotel",
            "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
            "Category": "Suite",
            "Tags": [ "restaurant", "bar", "continental breakfast" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.80,
            "Address": 
                {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "4",
            "HotelName": "Sublime Palace Hotel",
            "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
            "Category": "Luxury",
            "Tags": [ "concierge", "view", "air conditioning" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2020-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
                {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
                }
            }
          ]
        }
    
  2. Selecteer onder ### Upload documentsVerzenden aanvraag.

    U moet een HTTP/1.1 200 OK antwoord ontvangen waarvan de hoofdtekst de sleutel en status van elk geüpload document bevat.

Over de uploadaanvraag

In deze quickstart wordt Documenten - Index (REST API) aangeroepen om vier voorbeeldhoteldocumenten aan uw index toe te voegen. In vergelijking met de vorige aanvraag wordt de URI uitgebreid met de docs verzameling en index bewerking.

Elk document in de value matrix vertegenwoordigt een hotel en bevat velden die overeenkomen met het indexschema. De @search.action parameter geeft de bewerking op die moet worden uitgevoerd voor elk document. In ons voorbeeld wordt het document met upload toegevoegd als het niet bestaat, of bijgewerkt als het wel bestaat.

Query's uitvoeren op de index

Nu documenten in uw index zijn geladen, kunt u zoeken in volledige tekst gebruiken om specifieke termen of woordgroepen in hun velden te vinden.

Een volledige-tekstquery uitvoeren op uw index:

  1. Plak de volgende aanvraag in uw bestand.

    ### Run a query
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
      {
          "search": "attached restaurant",
          "select": "HotelId, HotelName, Tags, Description",
          "searchFields": "Description, Tags",
          "count": true
      }
    
  2. Selecteer onder ### Run a queryVerzenden aanvraag.

    U ontvangt een HTTP/1.1 200 OK antwoord dat lijkt op het volgende voorbeeld, waarin één overeenkomend hoteldocument, de relevantiescore en de geselecteerde velden worden weergegeven.

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

Over de queryaanvraag

Deze quickstart roept Documenten - Search Post (REST API) aan om hoteldocumenten te vinden die voldoen aan uw zoekcriteria. De URI is nu gericht op de /docs/search bewerking.

Zoekaanvragen voor volledige tekst bevatten altijd een search parameter die de querytekst bevat. De querytekst kan een of meer termen, woordgroepen of operatoren bevatten. Daarnaast searchkunt u andere parameters opgeven om het zoekgedrag en de resultaten te verfijnen.

Onze query zoekt naar de termen 'bijgevoegd restaurant' in de Description velden Tags van elk hoteldocument. De select parameter beperkt de velden die worden geretourneerd in het antwoord op HotelId, HotelNameen TagsDescription. De count parameter vraagt het totale aantal overeenkomende documenten aan.

In deze quickstart gebruikt u de clientbibliotheek Azure.Search.Documents om een zoekindex te maken, laden en er query's op uit te voeren met voorbeeldgegevens voor zoekopdrachten in volledige tekst. Zoeken in volledige tekst maakt gebruik van Apache Lucene voor indexering en query's en het BM25-classificatie-algoritme voor scoreresultaten.

In deze quickstart worden fictieve hotelgegevens uit de opslagplaats azure-search-sample-data gebruikt om de index te vullen.

Aanbeveling

U kunt de broncode downloaden om te beginnen met een voltooid project of deze stappen volgen om uw eigen project te maken.

Vereisten

Vereisten voor Microsoft Entra-id

Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:

Resourcegegevens ophalen

U moet de volgende informatie ophalen om uw toepassing te verifiëren met uw Azure AI-Search-service:

Naam van de variabele Weergegeven als
SEARCH_API_ENDPOINT Deze waarde vindt u in Azure Portal. Selecteer uw zoekservice en selecteer vervolgens in het linkermenu Overzicht. De URL-waarde onder Essentials is het eindpunt dat u nodig hebt. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

Meer informatie over sleutelloze verificatie en het instellen van omgevingsvariabelen.

Instellingen

  1. Maak een nieuwe map full-text-quickstart die de toepassing bevat en open Visual Studio Code in die map met de volgende opdracht:

    mkdir full-text-quickstart && cd full-text-quickstart
    
  2. Maak de package.json opdracht met de volgende opdracht:

    npm init -y
    
  3. Werk de package.json app bij naar ECMAScript met de volgende opdracht:

    npm pkg set type=module
    
  4. Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor JavaScript met:

    npm install @azure/search-documents
    
  5. Installeer voor de aanbevolen verificatie zonder wachtwoord de Azure Identity-clientbibliotheek met:

    npm install @azure/identity
    

Een zoekindex maken, laden en er query's op uitvoeren

In de vorige sectie voor het instellen hebt u de Azure AI Search-clientbibliotheek en andere afhankelijkheden geïnstalleerd.

In deze sectie voegt u code toe om een zoekindex te maken, deze te laden met documenten en query's uit te voeren. U voert het programma uit om de resultaten in de console te zien. Zie de uitleg van de codesectie voor een gedetailleerde uitleg van de code .

De voorbeeldcode in deze quickstart maakt gebruik van Microsoft Entra-id voor de aanbevolen sleutelloze verificatie. Als u liever een API-sleutel gebruikt, kunt u het DefaultAzureCredential object vervangen door een AzureKeyCredential object.

const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
  1. Maak een nieuw bestand met de naam index.ts en plak de volgende code in 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": "Category",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Tags",
    			"type": "Collection(Edm.String)",
    			"searchable": true,
    			"filterable": true,
    			"sortable": false,
    			"facetable": true
    		},
    		{
    			"name": "ParkingIncluded",
    			"type": "Edm.Boolean",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "LastRenovationDate",
    			"type": "Edm.DateTimeOffset",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Rating",
    			"type": "Edm.Double",
    			"filterable": true,
    			"sortable": true,
    			"facetable": true
    		},
    		{
    			"name": "Address",
    			"type": "Edm.ComplexType",
    			"fields": [
    				{
    					"name": "StreetAddress",
    					"type": "Edm.String" as SearchFieldDataType,
    					"filterable": false,
    					"sortable": false,
    					"facetable": false,
    					"searchable": true
    				},
    				{
    					"name": "City",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "StateProvince",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "PostalCode",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "Country",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				}
    			]
    		}
    	],
    	"suggesters": [
    		{
    			"name": "sg",
    			"searchMode": "analyzingInfixMatching",
    			"sourceFields": [
    				"HotelName"
    			]
    		}
    	]
    };
    
    async function main() {
    
    	// Your search service endpoint
    	const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
    
    	// Use the recommended keyless credential instead of the AzureKeyCredential credential.
    	const credential = new DefaultAzureCredential();
    	//const credential = new AzureKeyCredential(Your search service admin key);
    
    	// Create a SearchIndexClient to send create/delete index commands
    	const searchIndexClient: SearchIndexClient = new SearchIndexClient(
    		searchServiceEndpoint,
    		credential
    	);
    
    	// Creating a search client to upload documents and issue queries
    	const indexName: string  = "hotels-quickstart";
        const searchClient: SearchClient<any> = searchIndexClient.getSearchClient(indexName);
    
        console.log('Checking if index exists...');
        await deleteIndexIfExists(searchIndexClient, indexName);
    
        console.log('Creating index...');
        let index: SearchIndex = await searchIndexClient.createIndex(indexDefinition);
        console.log(`Index named ${index.name} has been created.`);
    
        console.log('Uploading documents...');
        let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
        console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `);
    
        // waiting one second for indexing to complete (for demo purposes only)
        sleep(1000);
    
        console.log('Querying the index...');
        console.log();
        await sendQueries(searchClient);
    }
    
    async function deleteIndexIfExists(searchIndexClient: SearchIndexClient, indexName: string) {
        try {
            await searchIndexClient.deleteIndex(indexName);
            console.log('Deleting index...');
        } catch {
            console.log('Index does not exist yet.');
        }
    }
    
    async function sendQueries(searchClient: SearchClient<any>) {
        // Query 1
        console.log('Query #1 - search everything:');
        let searchOptions: any = {
            includeTotalCount: true,
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        let searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log(`Result count: ${searchResults.count}`);
        console.log();
    
    
        // Query 2
        console.log('Query #2 - search with filter, orderBy, and select:');
        let state = 'FL';
        searchOptions = {
            filter: odata`Address/StateProvince eq ${state}`,
            orderBy: ["Rating desc"],
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        searchResults = await searchClient.search("wifi", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 3
        console.log('Query #3 - limit searchFields:');
        searchOptions = {
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("sublime palace", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 4
        console.log('Query #4 - limit searchFields and use facets:');
        searchOptions = {
            facets: ["Category"],
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 5
        console.log('Query #5 - Lookup document:');
        let documentResult = await searchClient.getDocument('3');
        console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);
        console.log();
    }
    
    function sleep(ms: number) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    main().catch((err) => {
        console.error("The sample encountered an error:", err);
    });
    
  2. Maak een bestand met de naam hotels.json en plak de volgende code in hotels.json:

    {
        "value": [
            {
                "HotelId": "1",
                "HotelName": "Stay-Kay City Hotel",
                "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                "Category": "Boutique",
                "Tags": ["view", "air conditioning", "concierge"],
                "ParkingIncluded": false,
                "LastRenovationDate": "2022-01-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "677 5th Ave",
                    "City": "New York",
                    "StateProvince": "NY",
                    "PostalCode": "10022"
                }
            },
            {
                "HotelId": "2",
                "HotelName": "Old Century Hotel",
                "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
                "Category": "Boutique",
                "Tags": ["pool", "free wifi", "concierge"],
                "ParkingIncluded": "false",
                "LastRenovationDate": "2019-02-18T00:00:00Z",
                "Rating": 3.6,
                "Address": {
                    "StreetAddress": "140 University Town Center Dr",
                    "City": "Sarasota",
                    "StateProvince": "FL",
                    "PostalCode": "34243"
                }
            },
            {
                "HotelId": "3",
                "HotelName": "Gastronomic Landscape Hotel",
                "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
                "Category": "Suite",
                "Tags": ["restaurant, "bar", "continental breakfast"],
                "ParkingIncluded": "true",
                "LastRenovationDate": "2015-09-20T00:00:00Z",
                "Rating": 4.8,
                "Address": {
                    "StreetAddress": "3393 Peachtree Rd",
                    "City": "Atlanta",
                    "StateProvince": "GA",
                    "PostalCode": "30326"
                }
            },
            {
                "HotelId": "4",
                "HotelName": "Sublime Palace Hotel",
                "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.",
                "Category": "Boutique",
                "Tags": ["concierge", "view", "air conditioning"],
                "ParkingIncluded": true,
                "LastRenovationDate": "2020-02-06T00:00:00Z",
                "Rating": 4.6,
                "Address": {
                    "StreetAddress": "7400 San Pedro Ave",
                    "City": "San Antonio",
                    "StateProvince": "TX",
                    "PostalCode": "78216"
                }
            }
        ]
    }
    
  3. Maak het tsconfig.json bestand om de TypeScript-code te transpileren en kopieer de volgende code voor 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. Transpile van TypeScript naar JavaScript.

    tsc
    
  5. Meld u aan bij Azure met de volgende opdracht:

    az login
    
  6. Voer de JavaScript-code uit met de volgende opdracht:

    node index.js
    

Uitleg van de code

Index maken

Maak een bestand hotels_quickstart_index.json. Dit bestand definieert hoe Azure AI Search werkt met de documenten die u in de volgende stap laadt. Elk veld wordt geïdentificeerd door een name en heeft een opgegeven type. Elk veld heeft ook een reeks indexkenmerken die aangeven of Azure AI Search kan zoeken, filteren, sorteren en facet op het veld. De meeste velden zijn eenvoudige gegevenstypen, maar een aantal, zoals AddressType, is van een complex type waarmee u uitgebreide gegevensstructuren in uw index kunt maken. Meer informatie over ondersteunde gegevenstypen en indexkenmerken die worden beschreven in Create Index (REST).

We willen hotels_quickstart_index.json importeren, zodat de hoofdfunctie toegang heeft tot de indexdefinitie.

import indexDefinition from './hotels_quickstart_index.json';

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

In de hoofdfunctie maken we vervolgens een SearchIndexClient, die wordt gebruikt voor het maken en beheren van indexen voor Azure AI Search.

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

De index moet worden verwijderd als deze al bestaat. Deze bewerking is een veelvoorkomende procedure voor test-/democode.

Dit doet u door een eenvoudige functie te definiëren die probeert om de index te verwijderen.

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

Als u de functie wilt uitvoeren, halen we de indexnaam op uit de indexdefinitie en geven we de indexName door met de indexClient aan de functie deleteIndexIfExists().

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

Daarna kunt u de index maken met behulp van de methode createIndex().

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

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

Documenten laden

In Azure AI Search zijn documenten gegevensstructuren die zowel invoer zijn voor het indexeren als uitvoeren van query's. U kunt dergelijke gegevens naar de index pushen of een Indexeerfunctie gebruiken. In dit geval pushen we de documenten programmatisch naar de index.

De documentinvoer bestaat mogelijk uit rijen in een database, blobs in Blob Storage of, zoals in dit voorbeeld, JSON-documenten op een schijf. U kunt hotels.json downloaden of uw eigen hotels.json-bestand maken met de volgende inhoud:

Net als bij indexDefinition moeten we ook bovenaan index.ts importeren hotels.json, zodat de gegevens kunnen worden geopend in onze hoofdfunctie.

import hotelData from './hotels.json';

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

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

Als u gegevens in de zoekindex wilt indexeren, moet u nu een SearchClient maken. Terwijl de SearchIndexClient wordt gebruikt voor het maken en beheren van een index, wordt de SearchClient gebruikt voor het uploaden van documenten en het uitvoeren van query's op de index.

Er zijn twee manieren om een SearchClient maken. De eerste optie is het maken van een geheel nieuwe SearchClient:

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

U kunt ook de methode getSearchClient() van de SearchIndexClient gebruiken om de SearchClient te maken:

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

Nu de client is gedefinieerd, uploadt u de documenten in de zoekindex. In dit geval gebruiken we de mergeOrUploadDocuments() methode, waarmee de documenten worden geüpload of samengevoegd met een bestaand document als er al een document met dezelfde sleutel bestaat. Controleer vervolgens of de bewerking is geslaagd omdat ten minste het eerste document bestaat.

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

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

Voer het programma opnieuw uit met tsc && node index.ts. U ziet nu een iets andere reeks berichten dan in stap 1. Nu bestaat de index wel en u zou een bericht moeten zien over het verwijderen van de index voordat de nieuwe index wordt gemaakt en hierin gegevens worden geplaatst.

Voordat we de query's in de volgende stap uitvoeren, definieert u een functie om het programma één seconde te laten wachten. Dit is alleen bedoeld voor test- en demonstratiedoeleinden om te controleren of de indexering is voltooid en of de documenten beschikbaar zijn in de index voor onze query's.

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

Als u het programma één seconde wilt laten wachten, roept u de sleep functie aan:

sleep(1000);

Een index doorzoeken

Als er een index is gemaakt en documenten zijn geüpload, bent u klaar om query's naar de index te verzenden. In deze sectie verzenden we vijf verschillende query's naar de zoekindex om verschillende onderdelen van de queryfunctionaliteit te demonstreren die voor u beschikbaar zijn.

De query's worden als volgt geschreven in een sendQueries() functie die we in de hoofdfunctie aanroepen:

await sendQueries(searchClient);

Query's worden verzonden met behulp van de methode search() van searchClient. De eerste parameter is de zoektekst en de tweede parameter specificeert zoekopties.

Queryvoorbeeld 1

De eerste query zoekt *, wat gelijk is aan ‘zoeken in alle’ en selecteert drie van de velden in de index. Het is een best practice om alleen de velden te select die u nodig hebt, omdat het ophalen van overbodige gegevens een latentie kan veroorzaken bij uw query's.

De searchOptions voor deze query heeft ook includeTotalCount ingesteld op true, waardoor het aantal gevonden resultaten wat overeenkomt wordt geretourneerd.

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 resterende query's die hieronder worden beschreven, moeten ook worden toegevoegd aan de functie sendQueries(). Ze zijn hier gescheiden voor leesbaarheid.

Queryvoorbeeld 2

In de volgende query geven we de zoekterm "wifi" op en nemen we ook een filter op om alleen resultaten te retourneren waarvan de status gelijk is aan 'FL'. Resultaten worden ook gerangschikt op de Ratingvan het hotel.

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

Queryvoorbeeld 3

Vervolgens kan de zoekopdracht worden beperkt tot één doorzoekbaar veld met behulp van de parameter searchFields. Deze methode is een uitstekende optie om uw query efficiënter te maken als u weet dat u alleen geïnteresseerd bent in overeenkomsten in bepaalde velden.

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

Queryvoorbeeld 4

Een andere veelgebruikte optie die in een query moet worden opgenomen, is facets. Met facetten kunt u zelfgestuurd inzoomen op de resultaten in uw gebruikersinterface. De resultaten van facetten kunnen worden omgezet in selectievakjes in het resultaatvenster.

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

Queryvoorbeeld 5

De laatste query maakt gebruik van de methode getDocument() van de searchClient. Zo kunt u een document efficiënt ophalen met de bijbehorende sleutel.

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

Samenvatting van query's

De vorige query's tonen meerdere manieren om termen in een query te koppelen: zoekopdracht in volledige tekst, filters en automatisch aanvullen.

Zoekopdrachten en filters voor volledige tekst worden uitgevoerd met behulp van de searchClient.search methode. Een zoekquery kan worden doorgegeven in de searchText tekenreeks, terwijl een filterexpressie kan worden doorgegeven in de filter eigenschap van de SearchOptions klasse. Als u wilt filteren zonder te zoeken, geeft u '*' door voor de searchText parameter van de search methode. Als u wilt zoeken zonder te filteren, laat u de filter eigenschap uitgeschakeld of geeft u een SearchOptions instantie helemaal niet door.

De hulpbronnen opschonen

Wanneer u in uw eigen abonnement werkt, is het een goed idee om een project te voltooien door te bepalen of u nog steeds de resources nodig hebt die u hebt gemaakt. Resources die nog operationeel zijn, kunnen u geld kosten. U kunt resources afzonderlijk verwijderen of u kunt de resourcegroep verwijderen om de hele set resources te verwijderen.

In Azure Portal kunt u resources vinden en beheren door alle resources of resourcegroepen te selecteren in het linkerdeelvenster.

Als u een gratis service gebruikt, moet u er rekening mee houden dat u beperkt bent tot drie indexen, indexeerfuncties en gegevensbronnen. U kunt afzonderlijke items in Azure Portal verwijderen om onder de limiet te blijven.