Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service als u er nog geen hebt. Voor deze quickstart kunt u een gratis service gebruiken.
Vereisten voor Microsoft Entra-id
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:
Installeer de Azure CLI.
Wijs de
Search Service Contributor
enSearch Index Data Contributor
rollen toe aan uw gebruikersaccount. U kunt rollen toewijzen in Azure Portal onder Toegangsbeheer (IAM)>Roltoewijzing toevoegen. Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.
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
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
Maak een nieuwe consoletoepassing met de volgende opdracht:
dotnet new console
Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor .NET met:
dotnet add package Azure.Search.Documents
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra ID installeert u het Azure.Identity-pakket met:
dotnet add package Azure.Identity
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();
Plak in Program.cs de volgende code. Bewerk de
serviceName
enapiKey
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(); } } }
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; } } }
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; } } }
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; } } }
Maak een nieuw bestand met de naam Hotel.Methods.cs en plak de volgende code om een
ToString()
onderdrukking voor deHotel
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(); } } }
Maak een nieuw bestand met de naam Address.Methods.cs en plak de volgende code om een
ToString()
onderdrukking voor deAddress
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); } }
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:
- 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.
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 eenSimpleField
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, zoalsIsKey = 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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service als u er nog geen hebt. Voor deze quickstart kunt u een gratis service gebruiken.
Vereisten voor Microsoft Entra-id
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:
Installeer de Azure CLI.
Wijs de
Search Service Contributor
enSearch Index Data Contributor
rollen toe aan uw gebruikersaccount. U kunt rollen toewijzen in Azure Portal onder Toegangsbeheer (IAM)>Roltoewijzing toevoegen. Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.
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.
Installeer Apache Maven. Voer vervolgens uit
mvn -v
om de installatie te bevestigen.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>
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
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();
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")); } }
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 ""; } } }
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; }
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, isFilterable
isSortable
en isFacetable
moet expliciet worden toegeschreven, zoals wordt weergegeven in de vorige steekproef.
De zoekindex maken
In App.java
maakt 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.java
maakt 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.java
de 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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service als u er nog geen hebt. Voor deze quickstart kunt u een gratis service gebruiken.
Vereisten voor Microsoft Entra-id
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:
Installeer de Azure CLI.
Wijs de
Search Service Contributor
enSearch Index Data Contributor
rollen toe aan uw gebruikersaccount. U kunt rollen toewijzen in Azure Portal onder Toegangsbeheer (IAM)>Roltoewijzing toevoegen. Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.
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
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
Maak de
package.json
opdracht met de volgende opdracht:npm init -y
Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor JavaScript met:
npm install @azure/search-documents
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();
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); });
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" } } ] }
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" ] } ] }
Meld u aan bij Azure met de volgende opdracht:
az login
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 Rating
van 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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service of zoek een bestaande service in uw huidige abonnement. Voor deze quickstart kunt u een gratis service gebruiken.
De Azure CLI voor sleutelloze verificatie met Microsoft Entra-id.
PowerShell 7.3 of hoger. In deze quickstart wordt Invoke-RestMethod gebruikt om REST API-aanroepen te maken.
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:
Meld u aan bij Azure Portal en selecteer uw zoekservice.
In het linkerdeelvenster, selecteer Instellingen>Sleutels.
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.
Selecteer toegangsbeheer (IAM) in het linkerdeelvenster.
Selecteer Toevoegen>Roltoewijzing toevoegen.
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:
Meld u aan bij Azure Portal en selecteer uw zoekservice.
Selecteer Overzicht in het linkerdeelvenster.
Noteer de URL, die vergelijkbaar moet zijn met
https://my-service.search.windows.net
.
Verbinding maken met Azure AI Search
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:
Open PowerShell op uw lokale systeem.
Meld u aan bij uw Azure-abonnement. Als u meerdere abonnementen hebt, selecteert u het abonnement dat uw zoekservice bevat.
az login
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
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.
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"
Voer
Invoke-RestMethod
deze opdracht uit om een GET-aanvraag naar uw zoekservice te verzenden. VoegConvertTo-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:
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} ] } ] } "@
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"
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 type
en 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, zoalsEdm.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:
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" } } ] } "@
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"
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:
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'
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 search
kunt 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
, HotelName
en Tags
Description
. 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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service als u er nog geen hebt. Voor deze quickstart kunt u een gratis service gebruiken.
Visual Studio Code met de Python-extensie of een equivalente IDE met Python 3.10 of hoger. Als u geen geschikte versie van Python hebt geïnstalleerd, volgt u de instructies in de zelfstudie voor VS Code Python.
Vereisten voor Microsoft Entra-id
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:
Installeer de Azure CLI.
Wijs de
Search Service Contributor
enSearch Index Data Contributor
rollen toe aan uw gebruikersaccount. U kunt rollen toewijzen in Azure Portal onder Toegangsbeheer (IAM)>Roltoewijzing toevoegen. Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.
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.
Download of kopieer het voorbeeldnotebook vanuit GitHub.
Open het notebook in Visual Studio Code.
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.
Het kan even duren voordat het is ingesteld. Als u problemen ondervindt, raadpleegt u Python-omgevingen in VS Code.
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
Selecteer de notebook-kernel.
- Selecteer Kernel in de rechterbovenhoek van het notitieblok.
- 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 .
Zorg ervoor dat het notebook is geopend in de
.venv
kernel, zoals beschreven in de vorige sectie.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
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 eenAzureKeyCredential
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"
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)
Voer de cel Een indexcode maken uit om een zoekindex te maken.
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 zijnTags
deze velden , .Address/City
Address/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
Een Azure-account met een actief abonnement. Gratis een account maken
Een Azure AI-Search-service. Maak een service of zoek een bestaande service in uw huidige abonnement. Voor deze quickstart kunt u een gratis service gebruiken.
De Azure CLI voor sleutelloze verificatie met Microsoft Entra-id.
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:
Meld u aan bij Azure Portal en selecteer uw zoekservice.
In het linkerdeelvenster, selecteer Instellingen>Sleutels.
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.
Selecteer toegangsbeheer (IAM) in het linkerdeelvenster.
Selecteer Toevoegen>Roltoewijzing toevoegen.
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:
Meld u aan bij Azure Portal en selecteer uw zoekservice.
Selecteer Overzicht in het linkerdeelvenster.
Noteer de URL, die vergelijkbaar moet zijn met
https://my-service.search.windows.net
.Open een terminal op uw lokale systeem.
Meld u aan bij uw Azure-abonnement. Als u meerdere abonnementen hebt, selecteert u het abonnement dat uw zoekservice bevat.
az login
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:
Open Visual Studio Code op uw lokale systeem.
Maak een
.rest
of.http
bestand.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}}
Vervang de
@baseUrl
en@token
tijdelijke aanduidingen met de waarden die u hebt verkregen in Eindpunt en token ophalen. Voer geen aanhalingstekens in.Selecteer onder
### List existing indexes by name
Verzenden 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.
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:
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} ] } ] }
Selecteer onder
### Create a new index
Verzenden 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 type
en 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, zoalsEdm.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:
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" } } ] }
Selecteer onder
### Upload documents
Verzenden 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:
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 }
Selecteer onder
### Run a query
Verzenden 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 search
kunt 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
, HotelName
en Tags
Description
. 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
- Een Azure-account met een actief abonnement. Gratis een account maken
- Een Azure AI-Search-service. Maak een service als u er nog geen hebt. Voor deze quickstart kunt u een gratis service gebruiken.
Vereisten voor Microsoft Entra-id
Voor de aanbevolen sleutelloze verificatie met Microsoft Entra-id moet u het volgende doen:
Installeer de Azure CLI.
Wijs de
Search Service Contributor
enSearch Index Data Contributor
rollen toe aan uw gebruikersaccount. U kunt rollen toewijzen in Azure Portal onder Toegangsbeheer (IAM)>Roltoewijzing toevoegen. Zie Verbinding maken met Azure AI Search met behulp van rollen voor meer informatie.
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
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
Maak de
package.json
opdracht met de volgende opdracht:npm init -y
Werk de
package.json
app bij naar ECMAScript met de volgende opdracht:npm pkg set type=module
Installeer de Azure AI Search-clientbibliotheek (Azure.Search.Documents) voor JavaScript met:
npm install @azure/search-documents
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();
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); });
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" } } ] }
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"] }
Transpile van TypeScript naar JavaScript.
tsc
Meld u aan bij Azure met de volgende opdracht:
az login
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 Rating
van 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.