Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
I den här snabbstarten använder du klientbiblioteket Azure.Search.Documents för att skapa, läsa in och fråga ett sökindex med exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Krav för Microsoft Entra-ID
För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:
Installera verktyget Azure CLI.
Tilldela rollerna
Search Service ContributorochSearch Index Data Contributortill ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta resursinformation
Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:
| Variabelnamn | Värde |
|---|---|
SEARCH_API_ENDPOINT |
Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn.
Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net. |
Läs mer om nyckellös autentisering och inställning av miljövariabler.
Konfigurera
Skapa en ny mapp
full-text-quickstartsom ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:mkdir full-text-quickstart && cd full-text-quickstartSkapa ett nytt konsolprogram med följande kommando:
dotnet new consoleInstallera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för .NET med:
dotnet add package Azure.Search.DocumentsFör den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID installerar du Azure.Identity-paketet med:
dotnet add package Azure.IdentityFör den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID loggar du in på Azure med följande kommando:
az login
Skapa, läsa in och fråga ett sökindex
I föregående konfigurationsavsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket.
I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
I Program.cs klistrar du in följande kod. Redigera variablerna
serviceNameochapiKeymed söktjänstens namn och administratörs-API-nyckel.using System; using Azure; using Azure.Identity; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Models; namespace AzureSearch.Quickstart { class Program { static void Main(string[] args) { // Your search service endpoint Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/"); // Use the recommended keyless credential instead of the AzureKeyCredential credential. DefaultAzureCredential credential = new(); //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key"); // Create a SearchIndexClient to send create/delete index commands SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential); // Create a SearchClient to load and query documents string indexName = "hotels-quickstart"; SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential); // Delete index if it exists Console.WriteLine("{0}", "Deleting index...\n"); DeleteIndexIfExists(indexName, searchIndexClient); // Create index Console.WriteLine("{0}", "Creating index...\n"); CreateIndex(indexName, searchIndexClient); SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName); // Load documents Console.WriteLine("{0}", "Uploading documents...\n"); UploadDocuments(ingesterClient); // Wait 2 secondsfor indexing to complete before starting queries (for demo and console-app purposes only) Console.WriteLine("Waiting for indexing...\n"); System.Threading.Thread.Sleep(2000); // Call the RunQueries method to invoke a series of queries Console.WriteLine("Starting queries...\n"); RunQueries(searchClient); // End the program Console.WriteLine("{0}", "Complete. Press any key to end this program...\n"); Console.ReadKey(); } // Delete the hotels-quickstart index to reuse its name private static void DeleteIndexIfExists(string indexName, SearchIndexClient searchIndexClient) { searchIndexClient.GetIndexNames(); { searchIndexClient.DeleteIndex(indexName); } } // Create hotels-quickstart index private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient) { FieldBuilder fieldBuilder = new FieldBuilder(); var searchFields = fieldBuilder.Build(typeof(Hotel)); var definition = new SearchIndex(indexName, searchFields); var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" }); definition.Suggesters.Add(suggester); searchIndexClient.CreateOrUpdateIndex(definition); } // Upload documents in a single Upload request. private static void UploadDocuments(SearchClient searchClient) { IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create( IndexDocumentsAction.Upload( new Hotel() { HotelId = "1", HotelName = "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(); } } }I samma mapp skapar du en ny fil med namnet Hotel.cs och klistrar in följande kod. Den här koden definierar strukturen för ett hotelldokument.
using System; using System.Text.Json.Serialization; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; namespace AzureSearch.Quickstart { public partial class Hotel { [SimpleField(IsKey = true, IsFilterable = true)] public string HotelId { get; set; } [SearchableField(IsSortable = true)] public string HotelName { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)] public string Description { get; set; } [SearchableField(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; } } }Skapa en ny fil med namnet Hotel.cs och klistra in följande kod för att definiera strukturen för ett hotelldokument. Attribut i fältet avgör hur det används i ett program. Attributet måste till exempel
IsFilterabletilldelas till varje fält som stöder ett filteruttryck.using System; using System.Text.Json.Serialization; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; namespace AzureSearch.Quickstart { public partial class Hotel { [SimpleField(IsKey = true, IsFilterable = true)] public string HotelId { get; set; } [SearchableField(IsSortable = true)] public string HotelName { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)] public string Description { get; set; } [SearchableField(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; } } }Skapa en ny fil med namnet Address.cs och klistra in följande kod för att definiera strukturen för ett adressdokument.
using Azure.Search.Documents.Indexes; namespace AzureSearch.Quickstart { public partial class Address { [SearchableField(IsFilterable = true)] public string StreetAddress { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string City { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string StateProvince { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string PostalCode { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string Country { get; set; } } }Skapa en ny fil med namnet Hotel.Methods.cs och klistra in följande kod för att definiera en
ToString()åsidosättning förHotelklassen.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(); } } }Skapa en ny fil med namnet Address.Methods.cs och klistra in följande kod för att definiera en
ToString()åsidosättning förAddressklassen.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); } }Skapa och kör programmet med följande kommando:
dotnet run
Utdata innehåller meddelanden från Console.WriteLine, med tillägg av frågeinformation och resultat.
Förklara koden
I föregående avsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket. Du har lagt till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du körde programmet för att se resultatet i konsolen.
I det här avsnittet förklarar vi koden som du lade till i konsolprogrammet.
Skapa en sökklient
I Program.cs skapade du två klienter:
- SearchIndexClient skapar indexet.
- SearchClient läser in och frågar ett befintligt index.
Båda klienterna behöver slutpunkten för söktjänsten och autentiseringsuppgifterna som beskrevs tidigare i avsnittet resursinformation .
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
static void Main(string[] args)
{
// Your search service endpoint
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
// Use the recommended keyless credential instead of the AzureKeyCredential credential.
DefaultAzureCredential credential = new();
//AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
// Create a SearchIndexClient to send create/delete index commands
SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential);
// Create a SearchClient to load and query documents
string indexName = "hotels-quickstart";
SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential);
// REDACTED FOR BREVITY . . .
}
Skapa ett index
Den här snabbstarten skapar ett Hotell-index som du läser in med hotelldata och kör frågor mot. I det här steget definierar du fälten i indexet. Varje fältdefinition innehåller ett namn, en datatyp och attribut som avgör hur fältet används.
I det här exemplet används synkrona metoder i biblioteket Azure.Search.Documents för enkelhet och läsbarhet. För produktionsscenarier bör du dock använda asynkrona metoder för att hålla appen skalbar och dynamisk. Du skulle till exempel använda CreateIndexAsync i stället för CreateIndex.
Definiera strukturerna
Du skapade två hjälpklasser, Hotel.cs och Address.cs, för att definiera strukturen för ett hotelldokument och dess adress. Klassen Hotel innehåller fält för ett hotell-ID, namn, beskrivning, kategori, taggar, parkering, renoveringsdatum, betyg och adress. Klassen Address innehåller fält för gatuadress, ort, delstat/provins, postnummer och land/region.
I azure.search.documents-klientbiblioteket kan du använda SearchableField och SimpleField för att effektivisera fältdefinitioner. Båda är derivat av ett SearchField och kan förenkla koden:
SimpleFieldkan vara vilken datatyp som helst, är alltid inte sökbar (ignoreras för fulltextsökningsfrågor) och kan hämtas (inte dold). Andra attribut är inaktiverade som standard, men kan aktiveras. Du kan använda ettSimpleFieldför dokument-ID eller fält som endast används i filter, fasetter eller bedömningsprofiler. I så fall bör du tillämpa eventuella attribut som är nödvändiga för scenariot, till exempelIsKey = trueför ett dokument-ID. Mer information finns i SimpleFieldAttribute.cs i källkoden.SearchableFieldmåste vara en sträng och är alltid sökbar och hämtningsbar. Andra attribut är inaktiverade som standard, men kan aktiveras. Eftersom den här fälttypen är sökbar stöder den synonymer och det fullständiga komplementet av analysverktygsegenskaper. Mer information finns i SearchableFieldAttribute.cs i källkoden.
Oavsett om du använder det grundläggande SearchField API:et eller någon av hjälpmodellerna måste du uttryckligen aktivera attribut för filter, fasetter och sortering. Till exempel måste IsFilterable, IsSortable och IsFacetable uttryckligen tillskrivas, som du ser i föregående exempel.
Skapa sökindexet
I Program.cs skapar du ett SearchIndex-objekt och anropar sedan metoden CreateIndex för att uttrycka indexet i söktjänsten. Indexet innehåller också en SearchSuggester för att aktivera automatisk komplettering i de angivna fälten.
// Create hotels-quickstart index
private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient)
{
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));
var definition = new SearchIndex(indexName, searchFields);
var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
definition.Suggesters.Add(suggester);
searchIndexClient.CreateOrUpdateIndex(definition);
}
Läsa in dokument
Azure AI Search söker efter innehåll som lagras i tjänsten. I det här steget läser du in JSON-dokument som överensstämmer med hotellindexet du skapade.
I Azure AI Search är sökdokument datastrukturer som både är indata för indexering och utdata från frågor. Som hämtats från en extern datakälla kan dokumentindata vara rader i en databas, blobar i Blob Storage eller JSON-dokument på disk. I det här exemplet tar vi en genväg och bäddar in JSON-dokument för fyra hotell i själva koden.
När du laddar upp dokument måste du använda ett IndexDocumentsBatch-objekt . Ett IndexDocumentsBatch objekt innehåller en samling åtgärder, som var och en innehåller ett dokument och en egenskap som talar om för Azure AI Search vilken åtgärd som ska utföras (ladda upp, slå samman, ta bort och slå sammanEllerUpload).
I Program.cs skapar du en matris med dokument och indexåtgärder och skickar sedan matrisen till IndexDocumentsBatch. Följande dokument överensstämmer med indexet hotels-quickstart enligt definitionen i hotellklassen.
// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "1",
HotelName = "Stay-Kay City Hotel",
Description = "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
}
När du har initierat Objektet IndexDocumentsBatch kan du skicka det till indexet genom att anropa IndexDocuments på ditt SearchClient-objekt .
Du läser in dokument med SearchClient i Main(), men åtgärden kräver även administratörsbehörighet för tjänsten, som vanligtvis är associerad med SearchIndexClient. Ett sätt att konfigurera den här åtgärden är att hämta SearchClient genom SearchIndexClient (searchIndexClient i det här exemplet).
SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);
// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);
Eftersom vi har en konsolapp som kör alla kommandon sekventiellt lägger vi till en väntetid på 2 sekunder mellan indexering och frågor.
// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
Console.WriteLine("Waiting for indexing...\n");
System.Threading.Thread.Sleep(2000);
Fördröjningen på 2 sekunder kompenserar för indexering, vilket är asynkront, så att alla dokument kan indexeras innan frågorna körs. Kodning i en fördröjning är vanligtvis bara nödvändigt i demonstrationer, tester och exempelprogram.
Sök i ett index
Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.
Det här avsnittet lägger till två funktioner: frågelogik och resultat. För frågor använder du sökmetoden . Den här metoden tar söktext (frågesträngen) och andra alternativ.
Klassen SearchResults representerar resultatet.
I Program.csWriteDocuments skriver metoden ut sökresultat till konsolen.
// Write search results to console
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
foreach (SearchResult<Hotel> result in searchResults.GetResults())
{
Console.WriteLine(result.Document);
}
Console.WriteLine();
}
private static void WriteDocuments(AutocompleteResults autoResults)
{
foreach (AutocompleteItem result in autoResults.Results)
{
Console.WriteLine(result.Text);
}
Console.WriteLine();
}
Frågeexempel 1
Metoden RunQueries kör frågor och returnerar resultat. Resultatet är Hotellobjekt. Det här exemplet visar metodsignaturen och den första frågan. Den här frågan visar parametern Select som gör att du kan skapa resultatet med hjälp av valda fält från dokumentet.
// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient searchClient)
{
SearchOptions options;
SearchResults<Hotel> response;
// Query 1
Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
options = new SearchOptions()
{
IncludeTotalCount = true,
Filter = "",
OrderBy = { "" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Address/City");
response = searchClient.Search<Hotel>("*", options);
WriteDocuments(response);
// REDACTED FOR BREVITY
}
Frågeexempel 2
I den andra frågan söker du efter en term, lägger till ett filter som väljer dokument där Omdöme är större än 4 och sorterar sedan efter Klassificering i fallande ordning. Filter är ett booleskt uttryck som utvärderas över IsFilterable-fält i ett index. Filtrera frågor antingen inkludera eller exkludera värden. Därför finns det ingen relevanspoäng associerad med en filterfråga.
// Query 2
Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
options = new SearchOptions()
{
Filter = "Rating gt 4",
OrderBy = { "Rating desc" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Rating");
response = searchClient.Search<Hotel>("hotels", options);
WriteDocuments(response);
Frågeexempel 3
Den tredje frågan visar searchFields, som används för att begränsa en fulltextsökningsåtgärd till specifika fält.
// Query 3
Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n");
options = new SearchOptions()
{
SearchFields = { "Tags" }
};
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Tags");
response = searchClient.Search<Hotel>("pool", options);
WriteDocuments(response);
Frågeexempel 4
Den fjärde frågan visar facets, som kan användas för att strukturera en fasetterad navigeringsstruktur.
// Query 4
Console.WriteLine("Query #4: Facet on 'Category'...\n");
options = new SearchOptions()
{
Filter = ""
};
options.Facets.Add("Category");
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Category");
response = searchClient.Search<Hotel>("*", options);
WriteDocuments(response);
Frågeexempel 5
I den femte frågan returnerar du ett specifikt dokument. Ett dokumentuppslag är ett typiskt svar på OnClick händelsen i en resultatuppsättning.
// Query 5
Console.WriteLine("Query #5: Look up a specific document...\n");
Response<Hotel> lookupResponse;
lookupResponse = searchClient.GetDocument<Hotel>("3");
Console.WriteLine(lookupResponse.Value.HotelId);
Frågeexempel 6
Den sista frågan visar syntaxen för automatisk komplettering, som simulerar en partiell användarinmatning av sa som matchar två möjliga matchningar i de sourceFields som är associerade med den förslagsanvändare som du definierade i indexet.
// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
var autoresponse = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);
Sammanfattning av frågor
Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.
Fulltextsökning och -filter utförs med metoden SearchClient.Search . En sökfråga kan skickas i strängensearchText, medan ett filteruttryck kan skickas i filteregenskapen för klassen SearchOptions. Om du vill filtrera utan att söka skickar du "*" bara efter parametern searchTextför sökmetoden . Om du vill söka utan filtrering lämnar du Filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.
I den här snabbstarten använder du klientbiblioteket Azure.Search.Documents för att skapa, läsa in och fråga ett sökindex med exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Krav för Microsoft Entra-ID
För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:
Installera verktyget Azure CLI.
Tilldela rollerna
Search Service ContributorochSearch Index Data Contributortill ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta resursinformation
Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:
| Variabelnamn | Värde |
|---|---|
SEARCH_API_ENDPOINT |
Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn.
Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net. |
Läs mer om nyckellös autentisering och inställning av miljövariabler.
Konfigurera
Exemplet i den här snabbstarten fungerar med Java Runtime. Installera ett Java Development Kit, till exempel Azul Zulu OpenJDK. Microsoft Build of OpenJDK eller din önskade JDK bör också fungera.
Installera Apache Maven. Kör
mvn -vsedan för att bekräfta att installationen har slutförts.Skapa en ny
pom.xmlfil i roten av projektet och kopiera följande kod till den:<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>azure.search.sample</groupId> <artifactId>azuresearchquickstart</artifactId> <version>1.0.0-SNAPSHOT</version> <build> <sourceDirectory>src</sourceDirectory> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.7.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-search-documents</artifactId> <version>11.7.3</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-core</artifactId> <version>1.53.0</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.15.1</version> </dependency> </dependencies> </project>Installera beroendena, inklusive Azure AI Search-klientbiblioteket (Azure.Search.Documents) för Java- och Azure Identity-klientbiblioteket för Java med:
mvn clean dependency:copy-dependenciesFör den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID loggar du in på Azure med följande kommando:
az login
Skapa, läsa in och fråga ett sökindex
I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.
I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Skapa en ny fil med namnet App.java och klistra in följande kod i App.java:
import java.util.Arrays; import java.util.ArrayList; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.LocalDateTime; import java.time.LocalDate; import java.time.LocalTime; import com.azure.core.util.Configuration; import com.azure.core.util.Context; import com.azure.identity.DefaultAzureCredential; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.search.documents.SearchClient; import com.azure.search.documents.SearchClientBuilder; import com.azure.search.documents.indexes.SearchIndexClient; import com.azure.search.documents.indexes.SearchIndexClientBuilder; import com.azure.search.documents.indexes.models.IndexDocumentsBatch; import com.azure.search.documents.models.SearchOptions; import com.azure.search.documents.indexes.models.SearchIndex; import com.azure.search.documents.indexes.models.SearchSuggester; import com.azure.search.documents.util.AutocompletePagedIterable; import com.azure.search.documents.util.SearchPagedIterable; public class App { public static void main(String[] args) { // Your search service endpoint "https://<Put your search service NAME here>.search.windows.net/"; // Use the recommended keyless credential instead of the AzureKeyCredential credential. DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build(); //AzureKeyCredential credential = new AzureKeyCredential("<Your search service admin key>"); // Create a SearchIndexClient to send create/delete index commands SearchIndexClient searchIndexClient = new SearchIndexClientBuilder() .endpoint(searchServiceEndpoint) .credential(credential) .buildClient(); // Create a SearchClient to load and query documents String indexName = "hotels-quickstart-java"; SearchClient searchClient = new SearchClientBuilder() .endpoint(searchServiceEndpoint) .credential(credential) .indexName(indexName) .buildClient(); // Create Search Index for Hotel model searchIndexClient.createOrUpdateIndex( new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null)) .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName")))); // Upload sample hotel documents to the Search Index uploadDocuments(searchClient); // Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only) System.out.println("Waiting for indexing...\n"); try { Thread.sleep(2000); } catch (InterruptedException e) { } // Call the RunQueries method to invoke a series of queries System.out.println("Starting queries...\n"); RunQueries(searchClient); // End the program System.out.println("Complete.\n"); } // Upload documents in a single Upload request. private static void uploadDocuments(SearchClient searchClient) { var hotelList = new ArrayList<Hotel>(); var hotel = new Hotel(); hotel.hotelId = "1"; hotel.hotelName = "Stay-Kay City Hotel"; hotel.description = "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")); } }Skapa en ny fil med namnet Hotel.java och klistra in följande kod i Hotel.java:
import com.azure.search.documents.indexes.SearchableField; import com.azure.search.documents.indexes.SimpleField; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.annotation.JsonInclude.Include; import java.time.OffsetDateTime; /** * Model class representing a hotel. */ @JsonInclude(Include.NON_NULL) public class Hotel { /** * Hotel ID */ @JsonProperty("HotelId") @SimpleField(isKey = true) public String hotelId; /** * Hotel name */ @JsonProperty("HotelName") @SearchableField(isSortable = true) public String hotelName; /** * Description */ @JsonProperty("Description") @SearchableField(analyzerName = "en.microsoft") public String description; /** * 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 ""; } } }Skapa en ny fil med namnet Address.java och klistra in följande kod i Address.java:
import com.azure.search.documents.indexes.SearchableField; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonInclude.Include; /** * Model class representing an address. */ @JsonInclude(Include.NON_NULL) public class Address { /** * Street address */ @JsonProperty("StreetAddress") @SearchableField public String streetAddress; /** * City */ @JsonProperty("City") @SearchableField(isFilterable = true, isSortable = true, isFacetable = true) public String city; /** * State or province */ @JsonProperty("StateProvince") @SearchableField(isFilterable = true, isSortable = true, isFacetable = true) public String stateProvince; /** * Postal code */ @JsonProperty("PostalCode") @SearchableField(isFilterable = true, isSortable = true, isFacetable = true) public String postalCode; /** * Country */ @JsonProperty("Country") @SearchableField(isFilterable = true, isSortable = true, isFacetable = true) public String country; }Kör det nya konsolprogrammet:
javac Address.java App.java Hotel.java -cp ".;target\dependency\*" java -cp ".;target\dependency\*" App
Förklara koden
I föregående avsnitt skapade du ett nytt konsolprogram och installerade Azure AI Search-klientbiblioteket. Du har lagt till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du körde programmet för att se resultatet i konsolen.
I det här avsnittet förklarar vi koden som du lade till i konsolprogrammet.
Skapa en sökklient
I App.java skapade du två klienter:
- SearchIndexClient skapar indexet.
- SearchClient läser in och frågar ett befintligt index.
Båda klienterna behöver slutpunkten för söktjänsten och autentiseringsuppgifterna som beskrevs tidigare i avsnittet resursinformation.
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
public static void main(String[] args) {
// Your search service endpoint
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
// Use the recommended keyless credential instead of the AzureKeyCredential credential.
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
//AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
// Create a SearchIndexClient to send create/delete index commands
SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(credential)
.buildClient();
// Create a SearchClient to load and query documents
String indexName = "hotels-quickstart-java";
SearchClient searchClient = new SearchClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(credential)
.indexName(indexName)
.buildClient();
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
// REDACTED FOR BREVITY . . .
}
Skapa ett index
Den här snabbstarten skapar ett Hotell-index som du läser in med hotelldata och kör frågor mot. I det här steget definierar du fälten i indexet. Varje fältdefinition innehåller ett namn, en datatyp och attribut som avgör hur fältet används.
I det här exemplet används synkrona metoder i biblioteket Azure.Search.Documents för enkelhet och läsbarhet. För produktionsscenarier bör du dock använda asynkrona metoder för att hålla appen skalbar och dynamisk. Du skulle till exempel använda CreateIndexAsync i stället för CreateIndex.
Definiera strukturerna
Du skapade två hjälpklasser, Hotel.java och Address.java, för att definiera strukturen för ett hotelldokument och dess adress. Hotellklassen innehåller fält för ett hotell-ID, namn, beskrivning, kategori, taggar, parkering, renoveringsdatum, betyg och adress. Klassen Address innehåller fält för gatuadress, ort, delstat/provins, postnummer och land/region.
I azure.search.documents-klientbiblioteket kan du använda SearchableField och SimpleField för att effektivisera fältdefinitioner.
-
SimpleFieldkan vara vilken datatyp som helst, är alltid inte sökbar (ignoreras för fulltextsökningsfrågor) och kan hämtas (inte dold). Andra attribut är inaktiverade som standard, men kan aktiveras. Du kan använda simplefield för dokument-ID:er eller fält som endast används i filter, fasetter eller bedömningsprofiler. I så fall måste du tillämpa eventuella attribut som är nödvändiga för scenariot, till exempel IsKey = true för ett dokument-ID. -
SearchableFieldmåste vara en sträng och är alltid sökbar och hämtningsbar. Andra attribut är inaktiverade som standard, men kan aktiveras. Eftersom den här fälttypen är sökbar stöder den synonymer och det fullständiga komplementet av analysverktygsegenskaper.
Oavsett om du använder det grundläggande SearchField API:et eller någon av hjälpmodellerna måste du uttryckligen aktivera attribut för filter, fasetter och sortering. Till exempel isFilterable, isSortable, och isFacetable måste uttryckligen tillskrivas, som du ser i föregående exempel.
Skapa sökindexet
I App.javaskapar du ett SearchIndex objekt i main metoden och anropar createOrUpdateIndex sedan metoden för att skapa indexet i söktjänsten. Indexet innehåller även en SearchSuggester för att aktivera automatisk komplettering på de angivna fälten.
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
Läsa in dokument
Azure AI Search söker efter innehåll som lagras i tjänsten. I det här steget läser du in JSON-dokument som överensstämmer med hotellindexet du skapade.
I Azure AI Search är sökdokument datastrukturer som både är indata för indexering och utdata från frågor. Som hämtats från en extern datakälla kan dokumentindata vara rader i en databas, blobar i Blob Storage eller JSON-dokument på disk. I det här exemplet tar vi en genväg och bäddar in JSON-dokument för fyra hotell i själva koden.
När du laddar upp dokument måste du använda ett IndexDocumentsBatch-objekt . Ett IndexDocumentsBatch objekt innehåller en samling IndexActions, som var och en innehåller ett dokument och en egenskap som talar om för Azure AI Search vilken åtgärd som ska utföras (ladda upp, slå samman, ta bort och mergeOrUpload).
I App.javaskapar du dokument och indexåtgärder och skickar dem sedan till IndexDocumentsBatch. Följande dokument överensstämmer med indexet hotels-quickstart enligt definitionen i hotellklassen.
private static void uploadDocuments(SearchClient searchClient)
{
var hotelList = new ArrayList<Hotel>();
var hotel = new Hotel();
hotel.hotelId = "1";
hotel.hotelName = "Stay-Kay City Hotel";
hotel.description = "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");
}
}
När du har initierat IndexDocumentsBatch objektet kan du skicka det till indexet genom att anropa indexDocuments för objektet SearchClient .
Du läser in dokument med SearchClient i main(), men åtgärden kräver även administratörsbehörighet för tjänsten, som vanligtvis är associerad med SearchIndexClient. Ett sätt att konfigurera den här åtgärden är att hämta SearchClient genom SearchIndexClient (searchIndexClient i det här exemplet).
uploadDocuments(searchClient);
Eftersom vi har en konsolapp som kör alla kommandon sekventiellt lägger vi till en väntetid på 2 sekunder mellan indexering och frågor.
// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
System.out.println("Waiting for indexing...\n");
try
{
Thread.sleep(2000);
}
catch (InterruptedException e)
{
}
Fördröjningen på 2 sekunder kompenserar för indexering, vilket är asynkront, så att alla dokument kan indexeras innan frågorna körs. Kodning i en fördröjning är vanligtvis bara nödvändigt i demonstrationer, tester och exempelprogram.
Sök i ett index
Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.
Det här avsnittet lägger till två funktioner: frågelogik och resultat. För frågor använder du sökmetoden. Den här metoden tar söktext (frågesträngen) och andra alternativ.
App.java I WriteDocumentsskriver metoden ut sökresultat till konsolen.
// Write search results to console
private static void WriteSearchResults(SearchPagedIterable searchResults)
{
searchResults.iterator().forEachRemaining(result ->
{
Hotel hotel = result.getDocument(Hotel.class);
System.out.println(hotel);
});
System.out.println();
}
// Write autocomplete results to console
private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
{
autocompleteResults.iterator().forEachRemaining(result ->
{
String text = result.getText();
System.out.println(text);
});
System.out.println();
}
Frågeexempel 1
Metoden RunQueries kör frågor och returnerar resultat. Resultatet är Hotellobjekt. Det här exemplet visar metodsignaturen och den första frågan. Den här frågan visar parametern Select som gör att du kan skapa resultatet med hjälp av valda fält från dokumentet.
// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient searchClient)
{
// Query 1
System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");
SearchOptions options = new SearchOptions();
options.setIncludeTotalCount(true);
options.setFilter("");
options.setOrderBy("");
options.setSelect("HotelId", "HotelName", "Address/City");
WriteSearchResults(searchClient.search("*", options, Context.NONE));
}
Frågeexempel 2
I den andra frågan söker du efter en term, lägger till ett filter som väljer dokument där Omdöme är större än 4 och sorterar sedan efter Klassificering i fallande ordning. Filter är ett booleskt uttryck som utvärderas över isFilterable fält i ett index. Filtrera frågor antingen inkludera eller exkludera värden. Därför finns det ingen relevanspoäng associerad med en filterfråga.
// Query 2
System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");
options = new SearchOptions();
options.setFilter("Rating gt 4");
options.setOrderBy("Rating desc");
options.setSelect("HotelId", "HotelName", "Rating");
WriteSearchResults(searchClient.search("hotels", options, Context.NONE));
Frågeexempel 3
Den tredje frågan visar searchFields, som används för att begränsa en fulltextsökningsåtgärd till specifika fält.
// Query 3
System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");
options = new SearchOptions();
options.setSearchFields("Tags");
options.setSelect("HotelId", "HotelName", "Tags");
WriteSearchResults(searchClient.search("pool", options, Context.NONE));
Frågeexempel 4
Den fjärde frågan visar facets, som kan användas för att strukturera en fasetterad navigeringsstruktur.
// Query 4
System.out.println("Query #4: Facet on 'Category'...\n");
options = new SearchOptions();
options.setFilter("");
options.setFacets("Category");
options.setSelect("HotelId", "HotelName", "Category");
WriteSearchResults(searchClient.search("*", options, Context.NONE));
Frågeexempel 5
I den femte frågan returnerar du ett specifikt dokument.
// Query 5
System.out.println("Query #5: Look up a specific document...\n");
Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
System.out.println(lookupResponse.hotelId);
System.out.println();
Frågeexempel 6
Den sista frågan visar syntaxen för automatisk komplettering, vilket simulerar en partiell användarinmatning av s som matchar två möjliga matchningar i den sourceFields associerade med den förslagsanvändare som du definierade i indexet.
// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
Sammanfattning av frågor
Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.
Fulltextsökning och -filter utförs med metoden SearchClient.search . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter egenskapen för klassen SearchOptions . Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.
I den här snabbstarten använder du klientbiblioteket Azure.Search.Documents för att skapa, läsa in och fråga ett sökindex med exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Krav för Microsoft Entra-ID
För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:
Installera verktyget Azure CLI.
Tilldela rollerna
Search Service ContributorochSearch Index Data Contributortill ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta resursinformation
Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:
| Variabelnamn | Värde |
|---|---|
SEARCH_API_ENDPOINT |
Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn.
Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net. |
Läs mer om nyckellös autentisering och inställning av miljövariabler.
Konfigurera
Skapa en ny mapp
full-text-quickstartsom ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:mkdir full-text-quickstart && cd full-text-quickstartpackage.jsonSkapa med följande kommando:npm init -yInstallera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för JavaScript med:
npm install @azure/search-documentsFör den rekommenderade lösenordslösa autentiseringen installerar du Azure Identity-klientbiblioteket med:
npm install @azure/identity
Skapa, läsa in och fråga ett sökindex
I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.
I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Skapa en ny fil med namnet index.js och klistra in följande kod i index.js:
// Import from the @azure/search-documents library import { SearchIndexClient, odata } from "@azure/search-documents"; // Import from the Azure Identity library import { DefaultAzureCredential } from "@azure/identity"; // Importing the hotels sample data import hotelData from './hotels.json' assert { type: "json" }; // Load the .env file if it exists import * as dotenv from "dotenv"; dotenv.config(); // Defining the index definition const indexDefinition = { "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "Description_fr", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "fr.lucene" }, { "name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true }, { "name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true }, { "name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true }, { "name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true }, { "name": "Address", "type": "Edm.ComplexType", "fields": [ { "name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true }, { "name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true } ] } ], "suggesters": [ { "name": "sg", "searchMode": "analyzingInfixMatching", "sourceFields": [ "HotelName" ] } ] }; async function main() { // Your search service endpoint const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/"; // Use the recommended keyless credential instead of the AzureKeyCredential credential. const credential = new DefaultAzureCredential(); //const credential = new AzureKeyCredential(Your search service admin key); // Create a SearchIndexClient to send create/delete index commands const searchIndexClient = new SearchIndexClient(searchServiceEndpoint, credential); // Creating a search client to upload documents and issue queries const indexName = "hotels-quickstart"; const searchClient = searchIndexClient.getSearchClient(indexName); console.log('Checking if index exists...'); await deleteIndexIfExists(searchIndexClient, indexName); console.log('Creating index...'); let index = await searchIndexClient.createIndex(indexDefinition); console.log(`Index named ${index.name} has been created.`); console.log('Uploading documents...'); let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']); console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `); // waiting one second for indexing to complete (for demo purposes only) sleep(1000); console.log('Querying the index...'); console.log(); await sendQueries(searchClient); } async function deleteIndexIfExists(searchIndexClient, indexName) { try { await searchIndexClient.deleteIndex(indexName); console.log('Deleting index...'); } catch { console.log('Index does not exist yet.'); } } async function sendQueries(searchClient) { // Query 1 console.log('Query #1 - search everything:'); let searchOptions = { includeTotalCount: true, select: ["HotelId", "HotelName", "Rating"] }; let searchResults = await searchClient.search("*", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(`Result count: ${searchResults.count}`); console.log(); // Query 2 console.log('Query #2 - search with filter, orderBy, and select:'); let state = 'FL'; searchOptions = { filter: odata `Address/StateProvince eq ${state}`, orderBy: ["Rating desc"], select: ["HotelId", "HotelName", "Rating"] }; searchResults = await searchClient.search("wifi", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 3 console.log('Query #3 - limit searchFields:'); searchOptions = { select: ["HotelId", "HotelName", "Rating"], searchFields: ["HotelName"] }; searchResults = await searchClient.search("sublime 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); });Skapa en fil med namnet hotels.json och klistra in följande kod i 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" } } ] }Skapa en fil med namnet hotels_quickstart_index.json och klistra in följande kod i hotels_quickstart_index.json:
{ "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "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" ] } ] }Logga in på Azure med följande kommando:
az loginKör JavaScript-koden med följande kommando:
node index.js
Förklara koden
Skapa index
Filen hotels_quickstart_index.json definierar hur Azure AI Search fungerar med de dokument som du läser in i nästa steg. Varje fält identifieras av en name och har en angiven type. Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).
Med vår indexdefinition på plats vill vi importera hotels_quickstart_index.json överst i index.js så att huvudfunktionen kan komma åt indexdefinitionen.
const indexDefinition = require('./hotels_quickstart_index.json');
I huvudfunktionen skapar vi sedan en SearchIndexClient, som används för att skapa och hantera index för Azure AI Search.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Sedan vill vi ta bort indexet om det redan finns. Den här åtgärden är en vanlig metod för test-/demokod.
Det gör vi genom att definiera en enkel funktion som försöker ta bort indexet.
async function deleteIndexIfExists(indexClient, indexName) {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
För att köra funktionen extraherar vi indexnamnet från indexdefinitionen och skickar indexName med indexClient till deleteIndexIfExists() funktionen.
const indexName = indexDefinition["name"];
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Efter det är vi redo att skapa indexet med createIndex() -metoden.
console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);
console.log(`Index named ${index.name} has been created.`);
Läsa in dokument
I Azure AI Search är dokument datastrukturer som både är indata för indexering och utdata från frågor. Du kan skicka sådana data till indexet eller använda en indexerare. I det här fallet skickar vi programmatiskt dokumenten till indexet.
Dokumentindata kan vara rader i en databas, blobar i Blob Storage eller, som i det här exemplet, JSON-dokument på disk. På samma sätt som vi gjorde med indexDefinitionmåste vi också importera hotels.json överst i index.js så att data kan nås i vår huvudfunktion.
const hotelData = require('./hotels.json');
För att indexera data i sökindexet måste vi nu skapa en SearchClient.
SearchIndexClient Används för att skapa och hantera ett index, SearchClient men används för att ladda upp dokument och köra frågor mot indexet.
Det finns två sätt att skapa en SearchClient. Det första alternativet är att skapa en SearchClient från grunden:
const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));
Du kan också använda getSearchClient() metoden SearchIndexClient för för att skapa SearchClient:
const searchClient = indexClient.getSearchClient(indexName);
Nu när klienten har definierats laddar du upp dokumenten till sökindexet. I det här fallet använder mergeOrUploadDocuments() vi metoden som laddar upp dokumenten eller sammanfogar dem med ett befintligt dokument om det redan finns ett dokument med samma nyckel.
console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Sök i ett index
När ett index har skapats och dokument har laddats upp är du redo att skicka frågor till indexet. I det här avsnittet skickar vi fem olika frågor till sökindexet för att demonstrera olika frågefunktioner som är tillgängliga för dig.
Frågorna skrivs i en sendQueries() funktion som vi anropar i huvudfunktionen enligt följande:
await sendQueries(searchClient);
Frågor skickas med metoden search()searchClient. Den första parametern är söktexten och den andra parametern anger sökalternativ.
Frågeexempel 1
Den första frågan söker efter *, vilket motsvarar att söka efter allt och väljer tre av fälten i indexet. Det är en bra idé att bara select använda de fält du behöver eftersom onödiga data kan ge svarstid till dina frågor.
För searchOptions den här frågan har includeTotalCount också angetts till true, som returnerar antalet matchande resultat som hittades.
async function sendQueries(searchClient) {
console.log('Query #1 - search everything:');
let searchOptions = {
includeTotalCount: true,
select: ["HotelId", "HotelName", "Rating"]
};
let searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log(`Result count: ${searchResults.count}`);
// remaining queries go here
}
De återstående frågorna som beskrivs nedan bör också läggas till i sendQueries() funktionen. De är separerade här för läsbarhet.
Frågeexempel 2
I nästa fråga anger vi söktermen "wifi" och inkluderar även ett filter för att endast returnera resultat där tillståndet är lika med 'FL'. Resultaten beställs också av hotellets Rating.
console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: ["HotelId", "HotelName", "Rating"]
};
searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Frågeexempel 3
Därefter begränsas sökningen till ett enda sökbart fält med hjälp av parametern searchFields . Den här metoden är ett bra alternativ för att göra frågan mer effektiv om du vet att du bara är intresserad av matchningar i vissa fält.
console.log('Query #3 - Limit searchFields:');
searchOptions = {
select: ["HotelId", "HotelName", "Rating"],
searchFields: ["HotelName"]
};
searchResults = await searchClient.search("Sublime Palace", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log();
Frågeexempel 4
Ett annat vanligt alternativ att ta med i en fråga är facets. Med fasetter kan du skapa filter i användargränssnittet för att göra det enkelt för användarna att veta vilka värden de kan filtrera ned till.
console.log('Query #4 - Use facets:');
searchOptions = {
facets: ["Category"],
select: ["HotelId", "HotelName", "Rating"],
searchFields: ["HotelName"]
};
searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Frågeexempel 5
Den sista frågan använder getDocument() metoden för searchClient. På så sätt kan du effektivt hämta ett dokument med dess nyckel.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Sammanfattning av frågor
Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.
Fulltextsökning och -filter utförs med hjälp av searchClient.search metoden . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter klassens SearchOptions egenskap. Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.
I den här snabbstarten använder du PowerShell och REST API:er för Azure AI Search för att skapa, läsa in och fråga ett sökindex för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst eller hitta en befintlig tjänst i din aktuella prenumeration. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Azure CLI för nyckellös autentisering med Microsoft Entra-ID.
PowerShell 7.3 eller senare. Den här snabbstarten använder Invoke-RestMethod för att göra REST API-anrop.
Konfigurera åtkomst
Du kan ansluta till din Azure AI Search-tjänst med hjälp av API-nycklar eller Microsoft Entra-ID med rolltilldelningar. Nycklar är enklare att börja med, men rollerna är säkrare.
Så här konfigurerar du den rekommenderade rollbaserade åtkomsten:
Logga in på Azure-portalen och välj din söktjänst.
Välj Inställningar>Nycklar i den vänstra rutan.
Under API-åtkomstkontroll väljer du Båda.
Det här alternativet möjliggör både nyckelbaserad och nyckellös autentisering. När du har tilldelat roller kan du återgå till det här steget och välja Rollbaserad åtkomstkontroll.
Välj Åtkomstkontroll (IAM) i den vänstra rutan.
Välj Lägg till>Lägg till rolltilldelning.
Tilldela rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto.
Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta slutpunkt
I nästa avsnitt anger du följande slutpunkt för att upprätta en anslutning till din Azure AI Search-tjänst. De här stegen förutsätter att du har konfigurerat rollbaserad åtkomst.
Så här hämtar du tjänstslutpunkten:
Logga in på Azure-portalen och välj din söktjänst.
Välj Översikt i den vänstra rutan.
Anteckna URL:en, som bör likna
https://my-service.search.windows.net.
Ansluta till Azure AI Search
Innan du kan göra REST API-anrop till din Azure AI Search-tjänst måste du autentisera och ansluta till tjänsten. Du utför följande steg i PowerShell, som stöder De Azure CLI-kommandon som används i steg två och tre.
Så här ansluter du till söktjänsten:
Öppna PowerShell i det lokala systemet.
Logga in på din Azure-prenumeration. Om du har flera prenumerationer väljer du den som innehåller söktjänsten.
az loginSkapa ett
$tokenobjekt för att lagra din åtkomsttoken.$token = az account get-access-token --resource https://search.azure.com/ --query accessToken --output tsvSkapa ett
$headersobjekt för att lagra din token och innehållstyp.$headers = @{ 'Authorization' = "Bearer $token" 'Content-Type' = 'application/json' 'Accept' = 'application/json' }Du behöver bara ange headern en gång per session, men du måste lägga till den i varje förfrågan.
Skapa ett
$urlobjekt som riktar sig till indexsamlingen i söktjänsten. Ersätt<YOUR-SEARCH-SERVICE>med det värde som du fick i Hämta slutpunkt.$url = "<YOUR-SEARCH-SERVICE>/indexes?api-version=2025-09-01&`$select=name"Kör
Invoke-RestMethodför att skicka en GET-begäran till din söktjänst. InkluderaConvertTo-Jsonför att visa svar från tjänsten.Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-JsonOm tjänsten är tom och inte har några index liknar svaret följande exempel. Annars visas en JSON-representation av indexdefinitioner.
{ "@odata.context": "https://my-service.search.windows.net/$metadata#indexes", "value": [ ] }
Skapa ett sökindex
Innan du lägger till innehåll i Azure AI Search måste du skapa ett index för att definiera hur innehållet lagras och struktureras. Ett index liknar en tabell i en relationsdatabas, men är särskilt utformat för sökåtgärder, till exempel fulltextsökning.
Kör följande kommandon i samma PowerShell-session som du startade i föregående avsnitt.
Så här skapar du ett index:
Skapa ett
$bodyobjekt för att definiera indexschemat.$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} ] } ] } "@Uppdatera objektet
$urlför att rikta in sig på det nya indexet. Ersätt<YOUR-SEARCH-SERVICE>med det värde som du fick i Hämta slutpunkt.$url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart?api-version=2025-09-01"Kör
Invoke-RestMethodför att skapa indexet för söktjänsten.Invoke-RestMethod -Uri $url -Headers $headers -Method Put -Body $body | ConvertTo-JsonSvaret bör innehålla JSON-representationen av indexschemat.
Om begäran om att skapa index
Den här snabbstarten anropar Index – Skapa (REST API) för att skapa ett sökindex med namnet hotels-quickstart och dess fysiska datastrukturer i söktjänsten.
I indexschemat fields definierar samlingen strukturen för hotelldokument. Varje fält har attributen name, data typeoch som avgör dess beteende under indexering och frågor. Fältet HotelId är markerat som nyckeln, som Azure AI Search kräver för att unikt identifiera varje dokument i ett index.
Viktiga punkter om indexschemat:
Använd strängfält (
Edm.String) för att göra numeriska data i fulltext sökbara. Andra datatyper som stöds, till exempelEdm.Int32, är filterbara, sorterbara, fasettbara och hämtningsbara men kan inte sökas.De flesta av våra fält är enkla datatyper, men du kan definiera komplexa typer för att representera kapslade data, till exempel fältet
Address.Fältattribut avgör tillåtna åtgärder. REST-API:erna tillåter många åtgärder som standard. Alla strängar kan till exempel sökas och hämtas. Med REST-API:erna kanske du bara använder attribut om du behöver inaktivera ett beteende.
Läs in indexet
Nyligen skapade index är tomma. Om du vill fylla i ett index och göra det sökbart måste du ladda upp JSON-dokument som överensstämmer med indexschemat.
I Azure AI Search fungerar dokument som både indata för indexering och utdata för frågor. För enkelhetens skull innehåller den här snabbstarten exempel på hotelldokument i inline-format som JSON. I produktionsscenarier hämtas dock innehåll ofta från anslutna datakällor och omvandlas till JSON med hjälp av indexerare.
Så här laddar du upp dokument till ditt index:
Skapa ett
$bodyobjekt för att lagra JSON-nyttolasten för fyra exempeldokument.$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" } } ] } "@Uppdatera objektet
$urlså att det riktar sig mot indexeringsslutpunkten. Ersätt<YOUR-SEARCH-SERVICE>med det värde som du fick i Hämta slutpunkt.$url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs/index?api-version=2025-09-01"Kör
Invoke-RestMethodför att skicka uppladdningsbegäran till söktjänsten.Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Body $body | ConvertTo-JsonSvaret bör innehålla nyckeln och statusen för varje uppladdat dokument.
Om uppladdningsbegäran
Den här snabbstarten anropar Dokument – Index (REST API) för att lägga till fyra exempel på hotelldokument i ditt index. Jämfört med föregående begäran utökas URI:n till att omfatta docs samlingen och index åtgärden.
Varje dokument i matrisen value representerar ett hotell och innehåller fält som matchar indexschemat. Parametern @search.action anger den åtgärd som ska utföras för varje dokument. I vårt exempel används upload, som lägger till dokumentet om det inte finns eller uppdaterar dokumentet om det finns.
Fråga indexet
Nu när dokument har lästs in i ditt index kan du använda fulltextsökning för att hitta specifika termer eller fraser i deras fält.
Så här kör du en fulltextfråga mot ditt index:
Uppdatera objektet
$urlför att ange sökparametrar. Ersätt<YOUR-SEARCH-SERVICE>med det värde som du fick i Hämta slutpunkt.$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2025-09-01&search=attached restaurant&searchFields=Description,Tags&$select=HotelId,HotelName,Tags,Description&$count=true'Kör
Invoke-RestMethodför att skicka frågebegäran till söktjänsten.Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-JsonSvaret bör likna följande exempel, som visar ett matchande hotelldokument, dess relevanspoäng och de valda fälten.
{ "@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" } ] }
Om frågebegäran
Den här snabbstarten anropar Dokument – Sök efter (REST API) för att hitta hotelldokument som matchar dina sökvillkor. URI:n riktar sig fortfarande mot docs samlingen men innehåller inte längre åtgärden index .
Begäranden om fulltextsökning innehåller alltid en search parameter som innehåller frågetexten. Frågetexten kan innehålla en eller flera termer, fraser eller operatorer. Förutom searchkan du ange andra parametrar för att förfina sökbeteendet och resultaten.
Vår fråga söker efter termerna "bifogad restaurang" i fälten Description och Tags i varje hotelldokument. Parametern $select begränsar fälten som returneras i svaret till HotelId, HotelName, Tagsoch Description. Parametern $count begär det totala antalet matchande dokument.
Andra frågeexempel
Kör följande kommandon för att utforska frågesyntaxen. Du kan utföra strängsökningar, använda $filter uttryck, begränsa resultatuppsättningar, välja specifika fält med mera. Kom ihåg att ersätta <YOUR-SEARCH-SERVICE> med det värde som du fick i Hämta slutpunkt.
# 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=2025-09-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=2025-09-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=2025-09-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=2025-09-01&search=pool&$orderby=Address/City asc&$select=HotelName, Address/City, Tags, Rating'
I den här snabbstarten använder du klientbiblioteket Azure.Search.Documents för att skapa, läsa in och fråga ett sökindex med exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned och köra en färdig notebook-fil.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Visual Studio Code med Python-tillägget eller en motsvarande IDE med Python 3.10 eller senare. Om du inte har installerat en lämplig version av Python följer du anvisningarna i VS Code Python-självstudien.
Krav för Microsoft Entra-ID
För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:
Installera verktyget Azure CLI.
Tilldela rollerna
Search Service ContributorochSearch Index Data Contributortill ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta resursinformation
Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:
| Variabelnamn | Värde |
|---|---|
SEARCH_API_ENDPOINT |
Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn.
Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net. |
Läs mer om nyckellös autentisering och inställning av miljövariabler.
Konfigurera din miljö
Du kör exempelkoden i en Jupyter-anteckningsbok. Därför måste du konfigurera din miljö för att köra Jupyter Notebooks.
Ladda ned eller kopiera exempelanteckningsboken från GitHub.
Öppna anteckningsboken i Visual Studio Code.
Skapa en ny Python-miljö som ska användas för att installera de paket du behöver för den här självstudien.
Viktigt!
Installera inte paket i din globala Python-installation. Du bör alltid använda en virtuell miljö eller conda-miljö när du installerar Python-paket, annars kan du avbryta din globala installation av Python.
Det kan ta en minut att konfigurera. Om du stöter på problem kan du läsa Python-miljöer i VS Code.
Installera Jupyter Notebooks och IPython Kernel for Jupyter Notebooks om du inte redan har dem.
pip install jupyter pip install ipykernel python -m ipykernel install --user --name=.venvVälj notebook-kerneln.
- I det övre högra hörnet i notebook-filen väljer du Välj kernel.
- Om du ser
.venvi listan väljer du den. Om du inte ser den väljer du >
Skapa, läsa in och fråga ett sökindex
I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .
Kontrollera att anteckningsboken är öppen i kerneln
.venvenligt beskrivningen i föregående avsnitt.Kör den första kodcellen för att installera de paket som krävs, inklusive azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet ! pip install azure-identity --quiet ! pip install python-dotenv --quietErsätt innehållet i den andra kodcellen med följande kod beroende på din autentiseringsmetod.
Kommentar
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet
DefaultAzureCredentialmed ettAzureKeyCredentialobjekt.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"Ta bort följande två rader från cellen Skapa en indexkod . Autentiseringsuppgifterna har redan angetts i den tidigare kodcellen.
from azure.core.credentials import AzureKeyCredential credential = AzureKeyCredential(search_api_key)Kör cellen Skapa en indexkod för att skapa ett sökindex.
Kör de återstående kodcellerna sekventiellt för att läsa in dokument och köra frågor.
Förklara koden
Skapa ett index
SearchIndexClient används för att skapa och hantera index för Azure AI Search. Varje fält identifieras av en name och har en angiven type.
Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).
Skapa en dokumentnyttolast och ladda upp dokument
Använd en indexåtgärd för åtgärdstypen, till exempel uppladdning eller sammanslagning och uppladdning. Dokument kommer från Exemplet HotelsData på GitHub.
Sök i ett index
Du kan få frågeresultat så snart det första dokumentet indexeras, men den faktiska testningen av indexet bör vänta tills alla dokument har indexerats.
Använd sökmetoden för klassen search.client.
Exempelfrågorna i notebook-filen är:
- Grundläggande fråga: Kör en tom sökning (
search=*), som returnerar en orankad lista (sökpoäng = 1,0) godtyckliga dokument. Eftersom det inte finns några kriterier inkluderas alla dokument i resultatet. - Termfråga: Lägger till hela termer i sökuttrycket ("wifi"). Den här frågan anger att resultaten endast innehåller de fälten i -instruktionen
select. Om du begränsar fälten som kommer tillbaka minimeras mängden data som skickas tillbaka över tråden och minskar sökfördröjningen. - Filtrerad fråga: Lägg till ett filteruttryck som bara returnerar de hotell med ett omdöme som är större än fyra, sorterat i fallande ordning.
- Fältomfång: Lägg till
search_fieldsi omfånget för frågekörning till specifika fält. - Fasetter: Generera fasetter för positiva matchningar som finns i sökresultat. Det finns inga noll matchningar. Om sökresultaten inte innehåller termen wifi visas inte wifi i den fasetterade navigeringsstrukturen.
- Slå upp ett dokument: Returnera ett dokument baserat på dess nyckel. Den här åtgärden är användbar om du vill visa detaljerad information när en användare väljer ett objekt i ett sökresultat.
- Komplettera automatiskt: Ange potentiella matchningar när användaren skriver i sökrutan. Autocomplete använder en suggester (
sg) för att veta vilka fält som innehåller potentiella matchningar för förslagsbegäranden. I den här snabbstarten ärTagsfälten ,Address/City,Address/Country. Om du vill simulera automatisk komplettering skickar du bokstäverna sa som en partiell sträng. Metoden för automatisk komplettering av SearchClient skickar tillbaka potentiella termmatchningar.
Ta bort indexet
Om du är klar med det här indexet kan du ta bort det genom att köra cellen Rensa kod. Om du tar bort onödiga index frigörs utrymme för att gå igenom fler snabbstarter och självstudier.
I den här snabbstarten använder du REST API:er för Azure AI Search för att skapa, läsa in och fråga ett sökindex för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
En Azure AI-tjänsten Search. Skapa en tjänst eller hitta en befintlig tjänst i din aktuella prenumeration. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Azure CLI för nyckellös autentisering med Microsoft Entra-ID.
Konfigurera åtkomst
Du kan ansluta till din Azure AI Search-tjänst med hjälp av API-nycklar eller Microsoft Entra-ID med rolltilldelningar. Nycklar är enklare att börja med, men rollerna är säkrare.
Så här konfigurerar du den rekommenderade rollbaserade åtkomsten:
Logga in på Azure-portalen och välj din söktjänst.
Välj Inställningar>Nycklar i den vänstra rutan.
Under API-åtkomstkontroll väljer du Båda.
Det här alternativet möjliggör både nyckelbaserad och nyckellös autentisering. När du har tilldelat roller kan du återgå till det här steget och välja Rollbaserad åtkomstkontroll.
Välj Åtkomstkontroll (IAM) i den vänstra rutan.
Välj Lägg till>Lägg till rolltilldelning.
Tilldela rollerna Search Service Contributor och Search Index Data Contributor till ditt användarkonto.
Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta slutpunkt och token
I nästa avsnitt anger du följande slutpunkt och token för att upprätta en anslutning till din Azure AI Search-tjänst. De här stegen förutsätter att du har konfigurerat rollbaserad åtkomst.
Så här hämtar du tjänstslutpunkten och token:
Logga in på Azure-portalen och välj din söktjänst.
Välj Översikt i den vänstra rutan.
Anteckna URL:en, som bör likna
https://my-service.search.windows.net.Öppna en terminal i det lokala systemet.
Logga in på din Azure-prenumeration. Om du har flera prenumerationer väljer du den som innehåller söktjänsten.
az loginAnteckna din Microsoft Entra-token.
az account get-access-token --scope https://search.azure.com/.default
Konfigurera din fil
Innan du kan göra REST API-anrop till din Azure AI Search-tjänst måste du skapa en fil för att lagra tjänstslutpunkten, autentiseringstoken och eventuella begäranden. REST-klienttillägget i Visual Studio Code stöder den här uppgiften.
Så här konfigurerar du din begärandefil:
Öppna Visual Studio Code i ditt lokala system.
Skapa en
.resteller.httpfil.Klistra in följande platshållare och förfrågan i filen.
@baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE @token = PUT-YOUR-PERSONAL-IDENTITY-TOKEN-HERE ### List existing indexes by name GET {{baseUrl}}/indexes?api-version=2025-09-01 HTTP/1.1 Authorization: Bearer {{token}}@baseUrlErsätt platshållarna och@tokenmed de värden som du fick i Hämta slutpunkt och token. Inkludera inte citattecken.Under
### List existing indexes by nameväljer du Skicka begäran.Ett svar bör visas i ett intilliggande fönster. Om du har befintliga index visas de. Annars är listan tom. Om HTTP-koden är
200 OKär du redo för nästa steg.
Skapa ett sökindex
Innan du lägger till innehåll i Azure AI Search måste du skapa ett index för att definiera hur innehållet lagras och struktureras. Ett index liknar en tabell i en relationsdatabas, men är särskilt utformat för sökåtgärder, till exempel fulltextsökning.
Så här skapar du ett index:
Klistra in följande begäran i filen.
### Create a new index POST {{baseUrl}}/indexes?api-version=2025-09-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} ] } ] }Under
### Create a new indexväljer du Skicka begäran.Du bör få ett
HTTP/1.1 201 Createdsvar vars brödtext innehåller JSON-representationen av indexschemat.
Om begäran om att skapa index
Den här snabbstarten anropar Index – Skapa (REST API) för att skapa ett sökindex med namnet hotels-quickstart och dess fysiska datastrukturer i söktjänsten.
I indexschemat fields definierar samlingen strukturen för hotelldokument. Varje fält har attributen name, data typeoch som avgör dess beteende under indexering och frågor. Fältet HotelId är markerat som nyckeln, som Azure AI Search kräver för att unikt identifiera varje dokument i ett index.
Viktiga punkter om indexschemat:
Använd strängfält (
Edm.String) för att göra numeriska data i fulltext sökbara. Andra datatyper som stöds, till exempelEdm.Int32, är filterbara, sorterbara, fasettbara och hämtningsbara men kan inte sökas.De flesta av våra fält är enkla datatyper, men du kan definiera komplexa typer för att representera kapslade data, till exempel fältet
Address.Fältattribut avgör tillåtna åtgärder. REST-API:erna tillåter många åtgärder som standard. Alla strängar kan till exempel sökas och hämtas. Med REST-API:erna kanske du bara använder attribut om du behöver inaktivera ett beteende.
Läs in indexet
Nyligen skapade index är tomma. Om du vill fylla i ett index och göra det sökbart måste du ladda upp JSON-dokument som överensstämmer med indexschemat.
I Azure AI Search fungerar dokument som både indata för indexering och utdata för frågor. För enkelhetens skull innehåller den här snabbstarten exempel på hotelldokument i inline-format som JSON. I produktionsscenarier hämtas dock innehåll ofta från anslutna datakällor och omvandlas till JSON med hjälp av indexerare.
Så här laddar du upp dokument till ditt index:
Klistra in följande begäran i filen.
### Upload documents POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version=2025-09-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" } } ] }Under
### Upload documentsväljer du Skicka begäran.Du bör få ett
HTTP/1.1 200 OKsvar vars brödtext innehåller nyckeln och statusen för varje uppladdat dokument.
Om uppladdningsbegäran
Den här snabbstarten anropar Dokument – Index (REST API) för att lägga till fyra exempel på hotelldokument i ditt index. Jämfört med föregående begäran utökas URI:n till att omfatta docs samlingen och index åtgärden.
Varje dokument i matrisen value representerar ett hotell och innehåller fält som matchar indexschemat. Parametern @search.action anger den åtgärd som ska utföras för varje dokument. I vårt exempel används upload, som lägger till dokumentet om det inte finns eller uppdaterar dokumentet om det finns.
Fråga indexet
Nu när dokument har lästs in i ditt index kan du använda fulltextsökning för att hitta specifika termer eller fraser i deras fält.
Så här kör du en fulltextfråga mot ditt index:
Klistra in följande begäran i filen.
### Run a query POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version=2025-09-01 HTTP/1.1 Content-Type: application/json Authorization: Bearer {{token}} { "search": "attached restaurant", "select": "HotelId, HotelName, Tags, Description", "searchFields": "Description, Tags", "count": true }Under
### Run a queryväljer du Skicka begäran.Du bör få ett
HTTP/1.1 200 OKsvar som liknar följande exempel, som visar ett matchande hotelldokument, dess relevanspoäng och dess valda fält.{ "@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" ] } ] }
Om frågebegäran
Den här snabbstarten anropar Dokument – Sök efter (REST API) för att hitta hotelldokument som matchar dina sökvillkor. URI:n riktar nu in sig på /docs/search åtgärden.
Begäranden om fulltextsökning innehåller alltid en search parameter som innehåller frågetexten. Frågetexten kan innehålla en eller flera termer, fraser eller operatorer. Förutom searchkan du ange andra parametrar för att förfina sökbeteendet och resultaten.
Vår fråga söker efter termerna "bifogad restaurang" i fälten Description och Tags i varje hotelldokument. Parametern select begränsar fälten som returneras i svaret till HotelId, HotelName, Tagsoch Description. Parametern count begär det totala antalet matchande dokument.
I den här snabbstarten använder du klientbiblioteket Azure.Search.Documents för att skapa, läsa in och fråga ett sökindex med exempeldata för fulltextsökning. Fulltextsökning använder Apache Lucene för indexering och frågor och BM25-rankningsalgoritmen för bedömning av resultat.
Den här snabbstarten använder fiktiva hotelldata från lagringsplatsen azure-search-sample-data för att fylla i indexet.
Dricks
Du kan ladda ned källkoden för att börja med ett färdigt projekt eller följa dessa steg för att skapa en egen.
Förutsättningar
- Ett Azure-konto med en aktiv prenumeration. Skapa ett konto kostnadsfritt.
- En Azure AI-tjänsten Search. Skapa en tjänst om du inte har någon. För den här snabbstarten kan du använda en kostnadsfri tjänst.
Krav för Microsoft Entra-ID
För den rekommenderade nyckellösa autentiseringen med Microsoft Entra-ID måste du:
Installera verktyget Azure CLI.
Tilldela rollerna
Search Service ContributorochSearch Index Data Contributortill ditt användarkonto. Du kan tilldela roller i Azure Portal under Åtkomstkontroll (IAM)>Lägg till rolltilldelning. Mer information finns i Ansluta till Azure AI Search med hjälp av roller.
Hämta resursinformation
Du måste hämta följande information för att autentisera ditt program med din Azure AI-tjänsten Search:
| Variabelnamn | Värde |
|---|---|
SEARCH_API_ENDPOINT |
Det här värdet finns i Azure Portal. Välj söktjänsten och välj sedan Översikt på den vänstra menyn.
Url-värdet under Essentials är den slutpunkt som du behöver. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net. |
Läs mer om nyckellös autentisering och inställning av miljövariabler.
Konfigurera
Skapa en ny mapp
full-text-quickstartsom ska innehålla programmet och öppna Visual Studio Code i mappen med följande kommando:mkdir full-text-quickstart && cd full-text-quickstartpackage.jsonSkapa med följande kommando:npm init -ypackage.jsonUppdatera till ECMAScript med följande kommando:npm pkg set type=moduleInstallera Azure AI Search-klientbiblioteket (Azure.Search.Documents) för JavaScript med:
npm install @azure/search-documentsFör den rekommenderade lösenordslösa autentiseringen installerar du Azure Identity-klientbiblioteket med:
npm install @azure/identity
Skapa, läsa in och fråga ett sökindex
I föregående konfigurationsavsnitt installerade du Azure AI Search-klientbiblioteket och andra beroenden.
I det här avsnittet lägger du till kod för att skapa ett sökindex, läsa in det med dokument och köra frågor. Du kör programmet för att se resultatet i konsolen. En detaljerad förklaring av koden finns i avsnittet förklara koden .
Exempelkoden i den här snabbstarten använder Microsoft Entra-ID för rekommenderad nyckellös autentisering. Om du föredrar att använda en API-nyckel kan du ersätta objektet DefaultAzureCredential med ett AzureKeyCredential objekt.
const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
Skapa en ny fil med namnet index.ts och klistra in följande kod i index.ts:
// Import from the @azure/search-documents library import { SearchIndexClient, SearchClient, SearchFieldDataType, AzureKeyCredential, odata, SearchIndex } from "@azure/search-documents"; // Import from the Azure Identity library import { DefaultAzureCredential } from "@azure/identity"; // Importing the hotels sample data import hotelData from './hotels.json' assert { type: "json" }; // Load the .env file if it exists import * as dotenv from "dotenv"; dotenv.config(); // Defining the index definition const indexDefinition: SearchIndex = { "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String" as SearchFieldDataType, "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "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); });Skapa en fil med namnet hotels.json och klistra in följande kod i 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" } } ] }tsconfig.jsonSkapa filen för att transpilera TypeScript-koden och kopiera följande kod för ECMAScript.{ "compilerOptions": { "module": "NodeNext", "target": "ES2022", // Supports top-level await "moduleResolution": "NodeNext", "skipLibCheck": true, // Avoid type errors from node_modules "strict": true // Enable strict type-checking options }, "include": ["*.ts"] }Transpilera från TypeScript till JavaScript.
tscLogga in på Azure med följande kommando:
az loginKör JavaScript-koden med följande kommando:
node index.js
Förklara koden
Skapa index
Skapa en fil hotels_quickstart_index.json. Den här filen definierar hur Azure AI Search fungerar med de dokument som du läser in i nästa steg. Varje fält identifieras av en name och har en angiven type. Varje fält har också en serie indexattribut som anger om Azure AI Search kan söka, filtrera, sortera och fasettera på fältet. De flesta av fälten är enkla datatyper, men vissa, som AddressType är komplexa typer som gör att du kan skapa omfattande datastrukturer i ditt index. Du kan läsa mer om datatyper som stöds och indexattribut som beskrivs i Skapa index (REST).
Vi vill importera hotels_quickstart_index.json så att huvudfunktionen kan komma åt indexdefinitionen.
import indexDefinition from './hotels_quickstart_index.json';
interface HotelIndexDefinition {
name: string;
fields: SimpleField[] | ComplexField[];
suggesters: SearchSuggester[];
};
const hotelIndexDefinition: HotelIndexDefinition = indexDefinition as HotelIndexDefinition;
I huvudfunktionen skapar vi sedan en SearchIndexClient, som används för att skapa och hantera index för Azure AI Search.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Sedan vill vi ta bort indexet om det redan finns. Den här åtgärden är en vanlig metod för test-/demokod.
Det gör vi genom att definiera en enkel funktion som försöker ta bort indexet.
async function deleteIndexIfExists(indexClient: SearchIndexClient, indexName: string): Promise<void> {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
För att köra funktionen extraherar vi indexnamnet från indexdefinitionen och skickar indexName med indexClient till deleteIndexIfExists() funktionen.
// Getting the name of the index from the index definition
const indexName: string = hotelIndexDefinition.name;
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Efter det är vi redo att skapa indexet med createIndex() -metoden.
console.log('Creating index...');
let index = await indexClient.createIndex(hotelIndexDefinition);
console.log(`Index named ${index.name} has been created.`);
Läsa in dokument
I Azure AI Search är dokument datastrukturer som både är indata för indexering och utdata från frågor. Du kan skicka sådana data till indexet eller använda en indexerare. I det här fallet skickar vi programmatiskt dokumenten till indexet.
Dokumentindata kan vara rader i en databas, blobar i Blob Storage eller, som i det här exemplet, JSON-dokument på disk. Du kan antingen ladda ned hotels.json eller skapa en egen hotels.json fil med följande innehåll:
På samma sätt som vi gjorde med indexDefinition måste vi också importera hotels.json överst i index.ts så att data kan nås i vår huvudfunktion.
import hotelData from './hotels.json';
interface Hotel {
HotelId: string;
HotelName: string;
Description: string;
Category: string;
Tags: string[];
ParkingIncluded: string | boolean;
LastRenovationDate: string;
Rating: number;
Address: {
StreetAddress: string;
City: string;
StateProvince: string;
PostalCode: string;
};
};
const hotels: Hotel[] = hotelData["value"];
För att indexera data i sökindexet måste vi nu skapa en SearchClient.
SearchIndexClient Används för att skapa och hantera ett index, SearchClient men används för att ladda upp dokument och köra frågor mot indexet.
Det finns två sätt att skapa en SearchClient. Det första alternativet är att skapa en SearchClient från grunden:
const searchClient = new SearchClient<Hotel>(endpoint, indexName, new AzureKeyCredential(apiKey));
Du kan också använda getSearchClient() metoden SearchIndexClient för för att skapa SearchClient:
const searchClient = indexClient.getSearchClient<Hotel>(indexName);
Nu när klienten har definierats laddar du upp dokumenten till sökindexet. I det här fallet använder mergeOrUploadDocuments() vi metoden som laddar upp dokumenten eller sammanfogar dem med ett befintligt dokument om det redan finns ett dokument med samma nyckel. Kontrollera sedan att åtgärden lyckades eftersom åtminstone det första dokumentet finns.
console.log("Uploading documents...");
const indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotels);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Kör programmet igen med tsc && node index.ts. Du bör se en något annorlunda uppsättning meddelanden än de du såg i steg 1. Den här gången finns indexet och du bör se ett meddelande om att ta bort det innan appen skapar det nya indexet och publicerar data till det.
Innan vi kör frågorna i nästa steg definierar du en funktion så att programmet väntar en sekund. Detta görs bara i test-/demosyfte för att säkerställa att indexeringen är klar och att dokumenten är tillgängliga i indexet för våra frågor.
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Om du vill att programmet ska vänta en sekund anropar du sleep funktionen:
sleep(1000);
Sök i ett index
När ett index har skapats och dokument har laddats upp är du redo att skicka frågor till indexet. I det här avsnittet skickar vi fem olika frågor till sökindexet för att demonstrera olika frågefunktioner som är tillgängliga för dig.
Frågorna skrivs i en sendQueries() funktion som vi anropar i huvudfunktionen enligt följande:
await sendQueries(searchClient);
Frågor skickas med metoden search()searchClient. Den första parametern är söktexten och den andra parametern anger sökalternativ.
Frågeexempel 1
Den första frågan söker efter *, vilket motsvarar att söka efter allt och väljer tre av fälten i indexet. Det är en bra idé att bara select använda de fält du behöver eftersom onödiga data kan ge svarstid till dina frågor.
För searchOptions den här frågan har includeTotalCount också angetts till true, vilket returnerar antalet matchande resultat som hittades.
async function sendQueries(
searchClient: SearchClient<Hotel>
): Promise<void> {
// Query 1
console.log('Query #1 - search everything:');
const selectFields: SearchFieldArray<Hotel> = [
"HotelId",
"HotelName",
"Rating",
];
const searchOptions1 = {
includeTotalCount: true,
select: selectFields
};
let searchResults = await searchClient.search("*", searchOptions1);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
console.log(`Result count: ${searchResults.count}`);
// remaining queries go here
}
De återstående frågorna som beskrivs nedan bör också läggas till i sendQueries() funktionen. De är separerade här för läsbarhet.
Frågeexempel 2
I nästa fråga anger vi söktermen "wifi" och inkluderar även ett filter för att endast returnera resultat där tillståndet är lika med 'FL'. Resultaten beställs också av hotellets Rating.
console.log('Query #2 - search with filter, orderBy, and select:');
let state = 'FL';
const searchOptions2 = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: selectFields
};
searchResults = await searchClient.search("wifi", searchOptions2);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Frågeexempel 3
Därefter begränsas sökningen till ett enda sökbart fält med hjälp av parametern searchFields . Den här metoden är ett bra alternativ för att göra frågan mer effektiv om du vet att du bara är intresserad av matchningar i vissa fält.
console.log('Query #3 - limit searchFields:');
const searchOptions3 = {
select: selectFields,
searchFields: ["HotelName"] as const
};
searchResults = await searchClient.search("Sublime Palace", searchOptions3);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Frågeexempel 4
Ett annat vanligt alternativ att ta med i en fråga är facets. Med fasetter kan du tillhandahålla självriktad detaljvisning från resultatet i användargränssnittet. Fasetteringsresultatet kan omvandlas till kryssrutor i resultatfönstret.
console.log('Query #4 - limit searchFields and use facets:');
const searchOptions4 = {
facets: ["Category"],
select: selectFields,
searchFields: ["HotelName"] as const
};
searchResults = await searchClient.search("*", searchOptions4);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Frågeexempel 5
Den sista frågan använder getDocument() metoden för searchClient. På så sätt kan du effektivt hämta ett dokument med dess nyckel.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Sammanfattning av frågor
Föregående frågor visar flera sätt att matcha termer i en fråga: fulltextsökning, filter och automatisk komplettering.
Fulltextsökning och -filter utförs med hjälp av searchClient.search metoden . En sökfråga kan skickas i strängen searchText , medan ett filteruttryck kan skickas i filter klassens SearchOptions egenskap. Om du vill filtrera utan att söka skickar du bara "*" för parametern searchText för search metoden. Om du vill söka utan filtrering lämnar du filter egenskapen oetig eller skickar inte någon SearchOptions instans alls.
Rensa resurser
När du arbetar i din egen prenumeration är det en bra idé att slutföra ett projekt genom att avgöra om du fortfarande behöver de resurser som du har skapat. Resurser som lämnas igång kan kosta dig pengar. Du kan ta bort resurser individuellt, eller så kan du ta bort resursgruppen för att ta bort hela uppsättningen resurser.
I Azure-portalen kan du hitta och hantera resurser genom att välja Alla resurser eller Resursgrupper i den vänstra rutan.
Om du använder en kostnadsfri tjänst ska du komma ihåg att du är begränsad till tre index, indexerare och datakällor. Du kan ta bort enskilda objekt i Azure Portal för att hålla dig under gränsen.