Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym krótkim przewodniku użyjesz biblioteki klienta Azure.Search.Documents do tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania z przykładowymi danymi na potrzeby wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten szybki start używa fikcyjnych danych hotelowych z repozytorium azure-search-sample-data do wypełnienia indeksu.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę , jeśli jej nie masz. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Wymagania wstępne dotyczące identyfikatora entra firmy Microsoft
W przypadku zalecanego uwierzytelniania bez klucza za pomocą identyfikatora Entra firmy Microsoft należy:
Zainstaluj interfejs wiersza polecenia platformy Azure.
Przypisz role
Search Service Contributor
iSearch Index Data Contributor
do swojego konta użytkownika. Role można przypisać w witrynie Azure Portal w obszarze Kontrola dostępu (IAM)>Dodawanie przypisania roli. Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobieranie informacji o zasobie
Aby uwierzytelnić aplikację przy użyciu usługi Azure AI usługa wyszukiwania, należy pobrać następujące informacje:
Nazwa zmiennej | Wartość |
---|---|
SEARCH_API_ENDPOINT |
Tę wartość można znaleźć w witrynie Azure Portal. Wybierz usługę wyszukiwania, a następnie z menu po lewej stronie wybierz pozycję Przegląd. Wartość adresu URL w obszarze Podstawy to potrzebny punkt końcowy. Przykładowy punkt końcowy może wyglądać podobnie jak https://mydemo.search.windows.net . |
Dowiedz się więcej na temat uwierzytelniania bez klucza i ustawiania zmiennych środowiskowych.
Konfiguruj
Utwórz nowy folder
full-text-quickstart
zawierający aplikację i otwórz program Visual Studio Code w tym folderze za pomocą następującego polecenia:mkdir full-text-quickstart && cd full-text-quickstart
Utwórz nową aplikację konsolową za pomocą następującego polecenia:
dotnet new console
Zainstaluj bibliotekę klienta usługi Azure AI Search (Azure.Search.Documents) dla platformy .NET przy użyciu następujących elementów:
dotnet add package Azure.Search.Documents
Aby uzyskać zalecane uwierzytelnianie bez klucza za pomocą identyfikatora Entra firmy Microsoft, zainstaluj pakiet Azure.Identity za pomocą polecenia:
dotnet add package Azure.Identity
Aby uzyskać zalecane uwierzytelnianie bez klucza przy użyciu identyfikatora Entra firmy Microsoft, zaloguj się na platformie Azure za pomocą następującego polecenia:
az login
Tworzenie, ładowanie i wykonywanie zapytań względem indeksu wyszukiwania
W poprzedniej sekcji konfiguracji utworzono nową aplikację konsolową i zainstalowano bibliotekę klienta usługi Azure AI Search.
W tej sekcji dodasz kod, aby utworzyć indeks wyszukiwania, załadować go przy użyciu dokumentów i uruchomić zapytania. Uruchom program, aby wyświetlić wyniki w konsoli programu . Aby uzyskać szczegółowe wyjaśnienie kodu, zobacz sekcję wyjaśniającą kod .
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
W Program.cs wklej następujący kod.
serviceName
Edytuj zmienne iapiKey
przy użyciu nazwy usługi wyszukiwania i klucza interfejsu API administratora.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(); } } }
W tym samym folderze utwórz nowy plik o nazwie Hotel.cs i wklej następujący kod. Ten kod definiuje strukturę dokumentu hotelowego.
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; } } }
Utwórz nowy plik o nazwie Hotel.cs i wklej następujący kod, aby zdefiniować strukturę dokumentu hotelowego. Atrybuty w polu określają sposób jej użycia w aplikacji. Na przykład
IsFilterable
atrybut musi być przypisany do każdego pola obsługującego wyrażenie filtru.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; } } }
Utwórz nowy plik o nazwie Address.cs i wklej następujący kod, aby zdefiniować strukturę dokumentu adresu.
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; } } }
Utwórz nowy plik o nazwie Hotel.Methods.cs i wklej następujący kod, aby zdefiniować
ToString()
przesłonięcia dlaHotel
klasy.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(); } } }
Utwórz nowy plik o nazwie
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); } }
Skompiluj i uruchom aplikację za pomocą następującego polecenia:
dotnet run
Dane wyjściowe obejmują komunikaty z elementu Console.WriteLine z dodawaniem informacji o zapytaniu i wynikach.
Wyjaśnienie kodu
W poprzednich sekcjach utworzono nową aplikację konsolową i zainstalowano bibliotekę klienta usługi Azure AI Search. Dodano kod umożliwiający utworzenie indeksu wyszukiwania, załadowanie go za pomocą dokumentów i uruchomienie zapytań. Uruchomiono program, aby wyświetlić wyniki w konsoli programu .
W tej sekcji wyjaśnimy kod dodany do aplikacji konsolowej.
Tworzenie klienta wyszukiwania
W Program.cs utworzono dwóch klientów:
- Element SearchIndexClient tworzy indeks.
- Element SearchClient ładuje istniejący indeks i wykonuje zapytanie względem istniejącego indeksu.
Oba klienci potrzebują punktu końcowego usługi wyszukiwania i poświadczeń opisanych wcześniej w sekcji informacji o zasobie.
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
static void Main(string[] args)
{
// Your search service endpoint
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
// Use the recommended keyless credential instead of the AzureKeyCredential credential.
DefaultAzureCredential credential = new();
//AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
// Create a SearchIndexClient to send create/delete index commands
SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential);
// Create a SearchClient to load and query documents
string indexName = "hotels-quickstart";
SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential);
// REDACTED FOR BREVITY . . .
}
Tworzenie indeksu
Ten przewodnik Szybki start tworzy indeks Hotels ładowany przy użyciu danych hotelowych i wykonywania zapytań względem. W tym kroku zdefiniujesz pola w indeksie. Każda definicja pola zawiera nazwę, typ danych i atrybuty określające sposób użycia pola.
W tym przykładzie metody synchroniczne biblioteki Azure.Search.Documents są używane dla uproszczenia i czytelności. Jednak w przypadku scenariuszy produkcyjnych należy użyć metod asynchronicznych, aby zapewnić skalowalność i elastyczność aplikacji. Na przykład należy użyć polecenia CreateIndexAsync zamiast polecenia CreateIndex.
Definiowanie struktur
Utworzono dwie klasy pomocnicze, Hotel.cs i Address.cs, aby zdefiniować strukturę dokumentu hotelowego i jego adresu. Klasa Hotel
zawiera pola dla identyfikatora hotelu, nazwy, opisu, kategorii, tagów, parkingu, daty renowacji, klasyfikacji i adresu. Klasa Address
zawiera pola adresów ulicznych, miasta, stanu/prowincji, kodu pocztowego i kraju/regionu.
W bibliotece klienta Azure.Search.Documents można użyć pól SearchableField i SimpleField, aby usprawnić definicje pól. Oba są pochodnymi pola wyszukiwania i mogą potencjalnie uprościć kod:
SimpleField
może być dowolnym typem danych, jest zawsze niemożliwy do przeszukiwania (ignorowany w przypadku zapytań wyszukiwania pełnotekstowego) i jest pobierany (nie jest ukryty). Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Można użyćSimpleField
elementu dla identyfikatorów dokumentów lub pól używanych tylko w filtrach, aspektach lub profilach oceniania. Jeśli tak, pamiętaj, aby zastosować wszelkie atrybuty niezbędne do scenariusza, takie jakIsKey = true
identyfikator dokumentu. Aby uzyskać więcej informacji, zobacz SimpleFieldAttribute.cs w kodzie źródłowym.SearchableField
musi być ciągiem i zawsze można wyszukiwać i pobierać. Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Ponieważ ten typ pola można wyszukiwać, obsługuje synonimy i pełne uzupełnienie właściwości analizatora. Aby uzyskać więcej informacji, zobacz SearchableFieldAttribute.cs w kodzie źródłowym.
Niezależnie od tego, czy używasz podstawowego SearchField
interfejsu API, czy jednego z modeli pomocnika, musisz jawnie włączyć atrybuty filtru, aspektu i sortowania. Na przykład IsFilterable, IsSortable i IsFacetable muszą być jawnie przypisane, jak pokazano w poprzednim przykładzie.
Tworzenie indeksu wyszukiwania
W Program.cs utworzysz obiekt SearchIndex, a następnie wywołasz metodę CreateIndex, aby wyrazić indeks w usłudze wyszukiwania. Indeks zawiera również element SearchSuggester umożliwiający automatyczne uzupełnianie w określonych polach.
// 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);
}
Ładowanie dokumentów
Usługa Azure AI Search wyszukuje zawartość przechowywaną w usłudze. W tym kroku załadujesz dokumenty JSON zgodne z utworzonym indeksem hotelowym.
W usłudze Azure AI Search dokumenty wyszukiwania to struktury danych, które są danymi wejściowymi do indeksowania i danych wyjściowych z zapytań. Dane wejściowe dokumentu uzyskane z zewnętrznego źródła danych mogą być wierszami w bazie danych, obiektami blob w usłudze Blob Storage lub dokumentami JSON na dysku. W tym przykładzie używamy skrótu i osadzamy dokumenty JSON dla czterech hoteli w samym kodzie.
Podczas przekazywania dokumentów należy użyć obiektu IndexDocumentsBatch . Obiekt IndexDocumentsBatch
zawiera kolekcję akcji, z których każda zawiera dokument i właściwość informującą usługę Azure AI Search o tym, jaką akcję wykonać (przekazywanie, scalanie, usuwanie i scalanieOrUpload).
W Program.cs utworzysz tablicę dokumentów i akcji indeksu, a następnie przekażesz tablicę do IndexDocumentsBatch
. Następujące dokumenty są zgodne z indeksem hotels-quickstart zdefiniowanym przez klasę hotelową.
// 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
}
Po zainicjowaniu obiektu IndexDocumentsBatch możesz wysłać go do indeksu, wywołując element IndexDocuments w obiekcie SearchClient.
Dokumenty są ładowane przy użyciu elementu SearchClient w Main()
programie , ale operacja wymaga również uprawnień administratora w usłudze, która jest zwykle skojarzona z elementem SearchIndexClient. Jednym ze sposobów skonfigurowania tej operacji jest pobranie elementu SearchClient za pośrednictwem SearchIndexClient
(searchIndexClient
w tym przykładzie).
SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);
// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);
Ponieważ mamy aplikację konsolową, która uruchamia wszystkie polecenia sekwencyjnie, dodamy 2-sekundowy czas oczekiwania między indeksowaniem a zapytaniami.
// 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);
2-sekundowe opóźnienie rekompensuje indeksowanie, co jest asynchroniczne, dzięki czemu wszystkie dokumenty można indeksować przed wykonaniem zapytań. Kodowanie w opóźnieniu jest zwykle konieczne tylko w przypadku pokazów, testów i przykładowych aplikacji.
Przeszukiwanie indeksu
Wyniki zapytania można uzyskać zaraz po indeksowanym pierwszym dokumencie, ale rzeczywiste testowanie indeksu powinno poczekać, aż wszystkie dokumenty zostaną zindeksowane.
W tej sekcji dodano dwie funkcje: logikę zapytań i wyniki. W przypadku zapytań użyj metody Search . Ta metoda przyjmuje tekst wyszukiwania (ciąg zapytania) i inne opcje.
Klasa SearchResults reprezentuje wyniki.
W Program.csWriteDocuments
metoda wyświetla wyniki wyszukiwania w konsoli programu .
// 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();
}
Przykład zapytania 1
Metoda RunQueries
wykonuje zapytania i zwraca wyniki. Wyniki to obiekty hotelowe. W tym przykładzie przedstawiono podpis metody i pierwsze zapytanie. To zapytanie demonstruje Select
parametr, który umożliwia tworzenie wyniku przy użyciu wybranych pól z dokumentu.
// 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
}
Przykład zapytania 2
W drugim zapytaniu wyszukaj termin, dodaj filtr, który wybiera dokumenty, w których ocena jest większa niż 4, a następnie sortuj według klasyfikacji w kolejności malejącej. Filter to wyrażenie logiczne, które jest obliczane za pośrednictwem pól IsFilterable w indeksie. Filtrowanie zapytań obejmuje lub wyklucza wartości. W związku z tym nie ma wskaźnika istotności skojarzonego z zapytaniem filtru.
// 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);
Przykład zapytania 3
Trzecie zapytanie demonstruje searchFields
metodę , używaną do określania zakresu operacji wyszukiwania pełnotekstowego do określonych pól.
// 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);
Przykład zapytania 4
Czwarte zapytanie demonstruje facets
metodę , która może służyć do struktury struktury nawigacji aspektowej.
// 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);
Przykład zapytania 5
W piątym zapytaniu zwróć określony dokument. Wyszukiwanie dokumentu to typowa odpowiedź na OnClick
zdarzenie w zestawie wyników.
// 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);
Przykład zapytania 6
Ostatnie zapytanie pokazuje składnię autouzupełniania, symulując częściowe dane wejściowe użytkownika sa , która rozpoznaje dwa możliwe dopasowania w polach źródłowych skojarzonych z sugerowanym elementem zdefiniowanym w indeksie.
// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
var autoresponse = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);
Podsumowanie zapytań
Poprzednie zapytania pokazują wiele sposobów dopasowywania terminów w zapytaniu: wyszukiwanie pełnotekstowe, filtry i autouzupełnianie.
Wyszukiwanie pełnotekstowe i filtry są wykonywane przy użyciu metody SearchClient.Search . Zapytanie wyszukiwania można przekazać w searchText
ciągu, a wyrażenie filtru można przekazać we właściwości Filter klasy SearchOptions. Aby filtrować bez wyszukiwania, wystarczy przekazać "*"
searchText
parametr metody Search . Aby wyszukać bez filtrowania, pozostaw Filter
właściwość niezastawioną lub nie przekazuj SearchOptions
w ogóle wystąpienia.
W tym szybkim starcie użyjesz biblioteki klienta Azure.Search.Documents do tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania z przykładowymi danymi do wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten szybki start używa fikcyjnych danych hotelowych z repozytorium azure-search-sample-data do wypełniania indeksu.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę , jeśli jej nie masz. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Wymagania wstępne dotyczące identyfikatora entra firmy Microsoft
W przypadku zalecanego uwierzytelniania bez klucza za pomocą identyfikatora Entra firmy Microsoft należy:
Zainstaluj interfejs wiersza polecenia platformy Azure.
Przypisz role
Search Service Contributor
iSearch Index Data Contributor
do swojego konta użytkownika. Role można przypisać w witrynie Azure Portal w obszarze Kontrola dostępu (IAM)>Dodawanie przypisania roli. Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobieranie informacji o zasobie
Aby uwierzytelnić aplikację przy użyciu usługi Azure AI usługa wyszukiwania, należy pobrać następujące informacje:
Nazwa zmiennej | Wartość |
---|---|
SEARCH_API_ENDPOINT |
Tę wartość można znaleźć w witrynie Azure Portal. Wybierz usługę wyszukiwania, a następnie z menu po lewej stronie wybierz pozycję Przegląd. Wartość adresu URL w obszarze Podstawy to potrzebny punkt końcowy. Przykładowy punkt końcowy może wyglądać podobnie jak https://mydemo.search.windows.net . |
Dowiedz się więcej na temat uwierzytelniania bez klucza i ustawiania zmiennych środowiskowych.
Konfiguruj
Przykład w tym przewodniku Szybki start współpracuje ze środowiskiem uruchomieniowym Języka Java. Zainstaluj zestaw Java Development Kit, taki jak Azul Zulu OpenJDK. Pakiet Microsoft Build zestawu OpenJDK lub preferowany zestaw JDK powinien również działać.
Zainstaluj narzędzie Apache Maven. Następnie uruchom polecenie
mvn -v
, aby potwierdzić pomyślną instalację.Utwórz nowy
pom.xml
plik w katalogu głównym projektu i skopiuj do niego następujący kod:<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>
Zainstaluj zależności, w tym bibliotekę klienta usługi Azure AI Search (Azure.Search.Documents) dla języka Java i bibliotekę klienta tożsamości platformy Azure dla języka Java za pomocą następujących elementów:
mvn clean dependency:copy-dependencies
Aby uzyskać zalecane uwierzytelnianie bez klucza przy użyciu identyfikatora Entra firmy Microsoft, zaloguj się na platformie Azure za pomocą następującego polecenia:
az login
Tworzenie, ładowanie i wykonywanie zapytań względem indeksu wyszukiwania
W poprzedniej sekcji konfiguracji zainstalowano bibliotekę klienta usługi Azure AI Search i inne zależności.
W tej sekcji dodasz kod, aby utworzyć indeks wyszukiwania, załadować go przy użyciu dokumentów i uruchomić zapytania. Uruchom program, aby wyświetlić wyniki w konsoli programu . Aby uzyskać szczegółowe wyjaśnienie kodu, zobacz sekcję wyjaśniającą kod .
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Utwórz nowy plik o nazwie App.java i wklej następujący kod do 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")); } }
Utwórz nowy plik o nazwie Hotel.java i wklej następujący kod do 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 ""; } } }
Utwórz nowy plik o nazwie Address.java i wklej następujący kod do 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; }
Uruchom nową aplikację konsolową:
javac Address.java App.java Hotel.java -cp ".;target\dependency\*" java -cp ".;target\dependency\*" App
Wyjaśnienie kodu
W poprzednich sekcjach utworzono nową aplikację konsolową i zainstalowano bibliotekę klienta usługi Azure AI Search. Dodano kod umożliwiający utworzenie indeksu wyszukiwania, załadowanie go za pomocą dokumentów i uruchomienie zapytań. Uruchomiono program, aby wyświetlić wyniki w konsoli programu .
W tej sekcji wyjaśnimy kod dodany do aplikacji konsolowej.
Tworzenie klienta wyszukiwania
W App.java utworzono dwóch klientów:
- Element SearchIndexClient tworzy indeks.
- Element SearchClient ładuje istniejący indeks i wykonuje zapytanie względem istniejącego indeksu.
Oba klienci potrzebują punktu końcowego usługi wyszukiwania i poświadczeń opisanych wcześniej w sekcji informacji o zasobie.
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
public static void main(String[] args) {
// Your search service endpoint
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
// Use the recommended keyless credential instead of the AzureKeyCredential credential.
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
//AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key");
// Create a SearchIndexClient to send create/delete index commands
SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(credential)
.buildClient();
// Create a SearchClient to load and query documents
String indexName = "hotels-quickstart-java";
SearchClient searchClient = new SearchClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(credential)
.indexName(indexName)
.buildClient();
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
// REDACTED FOR BREVITY . . .
}
Tworzenie indeksu
Ten przewodnik Szybki start tworzy indeks Hotels ładowany przy użyciu danych hotelowych i wykonywania zapytań względem. W tym kroku zdefiniujesz pola w indeksie. Każda definicja pola zawiera nazwę, typ danych i atrybuty określające sposób użycia pola.
W tym przykładzie metody synchroniczne biblioteki Azure.Search.Documents są używane dla uproszczenia i czytelności. Jednak w przypadku scenariuszy produkcyjnych należy użyć metod asynchronicznych, aby zapewnić skalowalność i elastyczność aplikacji. Na przykład należy użyć polecenia CreateIndexAsync zamiast polecenia CreateIndex.
Definiowanie struktur
Utworzono dwie klasy pomocnicze, Hotel.java i Address.java, aby zdefiniować strukturę dokumentu hotelowego i jego adres. Klasa Hotel zawiera pola dla identyfikatora hotelu, nazwy, opisu, kategorii, tagów, parkingu, daty renowacji, oceny i adresu. Klasa Address zawiera pola dla adresu ulicznego, miasta, stanu/prowincji, kodu pocztowego i kraju/regionu.
W bibliotece klienta Azure.Search.Documents można użyć pól SearchableField i SimpleField , aby usprawnić definicje pól.
-
SimpleField
może być dowolnym typem danych, jest zawsze niemożliwy do przeszukiwania (ignorowany w przypadku zapytań wyszukiwania pełnotekstowego) i jest pobierany (nie jest ukryty). Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Możesz użyć pola SimpleField dla identyfikatorów dokumentów lub pól używanych tylko w filtrach, aspektach lub profilach oceniania. Jeśli tak, pamiętaj, aby zastosować wszelkie atrybuty, które są niezbędne dla scenariusza, takie jak IsKey = true dla identyfikatora dokumentu. -
SearchableField
musi być ciągiem i zawsze można wyszukiwać i pobierać. Inne atrybuty są domyślnie wyłączone, ale można je włączyć. Ponieważ ten typ pola można wyszukiwać, obsługuje synonimy i pełne uzupełnienie właściwości analizatora.
Niezależnie od tego, czy używasz podstawowego SearchField
interfejsu API, czy jednego z modeli pomocnika, musisz jawnie włączyć atrybuty filtru, aspektu i sortowania. Na przykład isFilterable
, isSortable
i isFacetable
muszą być jawnie przypisane, jak pokazano w poprzednim przykładzie.
Tworzenie indeksu wyszukiwania
W App.java
pliku utworzysz SearchIndex
obiekt w metodzie main
, a następnie wywołaj createOrUpdateIndex
metodę , aby utworzyć indeks w usłudze wyszukiwania. Indeks zawiera również element umożliwiający SearchSuggester
włączenie autouzupełniania w określonych polach.
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
Ładowanie dokumentów
Usługa Azure AI Search wyszukuje zawartość przechowywaną w usłudze. W tym kroku załadujesz dokumenty JSON zgodne z utworzonym indeksem hotelowym.
W usłudze Azure AI Search dokumenty wyszukiwania to struktury danych, które są danymi wejściowymi do indeksowania i danych wyjściowych z zapytań. Dane wejściowe dokumentu uzyskane z zewnętrznego źródła danych mogą być wierszami w bazie danych, obiektami blob w usłudze Blob Storage lub dokumentami JSON na dysku. W tym przykładzie używamy skrótu i osadzamy dokumenty JSON dla czterech hoteli w samym kodzie.
Podczas przekazywania dokumentów należy użyć obiektu IndexDocumentsBatch . Obiekt IndexDocumentsBatch
zawiera kolekcję indeksów, z których każda zawiera dokument i właściwość informującą usługę Azure AI Search o tym, jaką akcję należy wykonać (przekazywanie, scalanie, usuwanie i scalanieOrUpload).
W App.java
programie tworzysz dokumenty i akcje indeksu, a następnie przekazujesz je do IndexDocumentsBatch
elementu . Następujące dokumenty są zgodne z indeksem hotels-quickstart zdefiniowanym przez klasę hotelową.
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");
}
}
Po zainicjowaniu obiektu można wysłać go do indeksu IndexDocumentsBatch
, wywołując element indexDocuments w SearchClient
obiekcie.
Dokumenty są ładowane przy użyciu elementu SearchClient w main()
programie , ale operacja wymaga również uprawnień administratora w usłudze, która jest zwykle skojarzona z elementem SearchIndexClient. Jednym ze sposobów skonfigurowania tej operacji jest pobranie elementu SearchClient za pośrednictwem SearchIndexClient
(searchIndexClient
w tym przykładzie).
uploadDocuments(searchClient);
Ponieważ mamy aplikację konsolową, która uruchamia wszystkie polecenia sekwencyjnie, dodamy 2-sekundowy czas oczekiwania między indeksowaniem a zapytaniami.
// 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)
{
}
2-sekundowe opóźnienie rekompensuje indeksowanie, co jest asynchroniczne, dzięki czemu wszystkie dokumenty można indeksować przed wykonaniem zapytań. Kodowanie w opóźnieniu jest zwykle konieczne tylko w przypadku pokazów, testów i przykładowych aplikacji.
Przeszukiwanie indeksu
Wyniki zapytania można uzyskać zaraz po indeksowanym pierwszym dokumencie, ale rzeczywiste testowanie indeksu powinno poczekać, aż wszystkie dokumenty zostaną zindeksowane.
W tej sekcji dodano dwie funkcje: logikę zapytań i wyniki. W przypadku zapytań użyj metody Search. Ta metoda przyjmuje tekst wyszukiwania (ciąg zapytania) i inne opcje.
W App.java
pliku WriteDocuments
metoda wyświetla wyniki wyszukiwania w konsoli programu .
// 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();
}
Przykład zapytania 1
Metoda RunQueries
wykonuje zapytania i zwraca wyniki. Wyniki to obiekty hotelowe. W tym przykładzie przedstawiono podpis metody i pierwsze zapytanie. To zapytanie demonstruje Select
parametr, który umożliwia tworzenie wyniku przy użyciu wybranych pól z dokumentu.
// 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));
}
Przykład zapytania 2
W drugim zapytaniu wyszukaj termin, dodaj filtr, który wybiera dokumenty, w których ocena jest większa niż 4, a następnie sortuj według klasyfikacji w kolejności malejącej. Filter jest wyrażeniem logicznym, które jest obliczane względem isFilterable
pól w indeksie. Filtrowanie zapytań obejmuje lub wyklucza wartości. W związku z tym nie ma wskaźnika istotności skojarzonego z zapytaniem filtru.
// 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));
Przykład zapytania 3
Trzecie zapytanie demonstruje searchFields
metodę , używaną do określania zakresu operacji wyszukiwania pełnotekstowego do określonych pól.
// 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));
Przykład zapytania 4
Czwarte zapytanie demonstruje facets
metodę , która może służyć do struktury struktury nawigacji aspektowej.
// 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));
Przykład zapytania 5
W piątym zapytaniu zwróć określony 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();
Przykład zapytania 6
Ostatnie zapytanie pokazuje składnię autouzupełniania, s, która rozwiązuje dwa możliwe dopasowania w sourceFields
skojarzonym z sugerowanym elementem zdefiniowanym w indeksie.
// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
Podsumowanie zapytań
Poprzednie zapytania pokazują wiele sposobów dopasowywania terminów w zapytaniu: wyszukiwanie pełnotekstowe, filtry i autouzupełnianie.
Wyszukiwanie pełnotekstowe i filtry są wykonywane przy użyciu metody SearchClient.search . Zapytanie wyszukiwania można przekazać w searchText
ciągu, a wyrażenie filtru można przekazać we filter
właściwości klasy SearchOptions . Aby filtrować bez wyszukiwania, wystarczy przekazać wartość "*" dla searchText
parametru search
metody . Aby wyszukać bez filtrowania, pozostaw filter
właściwość niezastawioną lub nie przekazuj SearchOptions
w ogóle wystąpienia.
W przewodniku szybkiego startu użyjesz biblioteki klienta Azure.Search.Documents do tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania z przykładowymi danymi na potrzeby wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten przewodnik szybkiego startu używa fikcyjnych danych hotelowych z repozytorium azure-search-sample-data, aby wypełnić indeks.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę , jeśli jej nie masz. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Wymagania wstępne dotyczące identyfikatora entra firmy Microsoft
W przypadku zalecanego uwierzytelniania bez klucza za pomocą identyfikatora Entra firmy Microsoft należy:
Zainstaluj interfejs wiersza polecenia platformy Azure.
Przypisz role
Search Service Contributor
iSearch Index Data Contributor
do swojego konta użytkownika. Role można przypisać w witrynie Azure Portal w obszarze Kontrola dostępu (IAM)>Dodawanie przypisania roli. Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobieranie informacji o zasobie
Aby uwierzytelnić aplikację przy użyciu usługi Azure AI usługa wyszukiwania, należy pobrać następujące informacje:
Nazwa zmiennej | Wartość |
---|---|
SEARCH_API_ENDPOINT |
Tę wartość można znaleźć w witrynie Azure Portal. Wybierz usługę wyszukiwania, a następnie z menu po lewej stronie wybierz pozycję Przegląd. Wartość adresu URL w obszarze Podstawy to potrzebny punkt końcowy. Przykładowy punkt końcowy może wyglądać podobnie jak https://mydemo.search.windows.net . |
Dowiedz się więcej na temat uwierzytelniania bez klucza i ustawiania zmiennych środowiskowych.
Konfiguruj
Utwórz nowy folder
full-text-quickstart
zawierający aplikację i otwórz program Visual Studio Code w tym folderze za pomocą następującego polecenia:mkdir full-text-quickstart && cd full-text-quickstart
Utwórz element
package.json
za pomocą następującego polecenia:npm init -y
Zainstaluj bibliotekę klienta usługi Azure AI Search (Azure.Search.Documents) dla języka JavaScript za pomocą następujących elementów:
npm install @azure/search-documents
W przypadku zalecanego uwierzytelniania bez hasła zainstaluj bibliotekę klienta tożsamości platformy Azure za pomocą polecenia:
npm install @azure/identity
Tworzenie, ładowanie i wykonywanie zapytań względem indeksu wyszukiwania
W poprzedniej sekcji konfiguracji zainstalowano bibliotekę klienta usługi Azure AI Search i inne zależności.
W tej sekcji dodasz kod, aby utworzyć indeks wyszukiwania, załadować go przy użyciu dokumentów i uruchomić zapytania. Uruchom program, aby wyświetlić wyniki w konsoli programu . Aby uzyskać szczegółowe wyjaśnienie kodu, zobacz sekcję wyjaśniającą kod .
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Utwórz nowy plik o nazwie index.js i wklej następujący kod do 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); });
Utwórz plik o nazwie hotels.json i wklej następujący kod do 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" } } ] }
Utwórz plik o nazwie hotels_quickstart_index.json i wklej następujący kod do 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" ] } ] }
Zaloguj się do platformy Azure przy użyciu następującego polecenia:
az login
Uruchom kod JavaScript za pomocą następującego polecenia:
node index.js
Wyjaśnienie kodu
tworzenie indeksu
Plik hotels_quickstart_index.json definiuje sposób działania usługi Azure AI Search z dokumentami ładowanymi w następnym kroku. Każde pole jest identyfikowane przez element name
i ma określony element type
. Każde pole ma również szereg atrybutów indeksu, które określają, czy usługa Azure AI Search może wyszukiwać, filtrować, sortować i aspekty po polu. Większość pól to proste typy danych, ale niektóre, takie jak AddressType
typy złożone, które umożliwiają tworzenie rozbudowanych struktur danych w indeksie. Więcej informacji na temat obsługiwanych typów danych i atrybutów indeksu opisano w artykule Create Index (REST) (Tworzenie indeksu (REST).
W naszej definicji indeksu chcemy zaimportować hotels_quickstart_index.json w górnej części index.js , aby funkcja główna mogła uzyskać dostęp do definicji indeksu.
const indexDefinition = require('./hotels_quickstart_index.json');
W ramach funkcji main utworzymy element SearchIndexClient
, który służy do tworzenia indeksów usługi Azure AI Search i zarządzania nimi.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Następnie chcemy usunąć indeks, jeśli już istnieje. Ta operacja jest powszechną praktyką w przypadku kodu testowego/demonstracyjnego.
Robimy to, definiując prostą funkcję, która próbuje usunąć indeks.
async function deleteIndexIfExists(indexClient, indexName) {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
Aby uruchomić funkcję, wyodrębniamy nazwę indeksu z definicji indeksu i przekazujemy indexName
element wraz z funkcją indexClient
deleteIndexIfExists()
.
const indexName = indexDefinition["name"];
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Następnie możemy utworzyć indeks za pomocą createIndex()
metody .
console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);
console.log(`Index named ${index.name} has been created.`);
Ładowanie dokumentów
W usłudze Azure AI Search dokumenty to struktury danych, które są danymi wejściowymi do indeksowania i danych wyjściowych z zapytań. Możesz wypchnąć takie dane do indeksu lub użyć indeksatora. W takim przypadku programowo wypchniemy dokumenty do indeksu.
Dane wejściowe dokumentu mogą być wierszami w bazie danych, obiektach blob w usłudze Blob Storage lub, jak w tym przykładzie, dokumentach JSON na dysku. Podobnie jak indexDefinition
w przypadku elementu , musimy również zaimportować hotels.json
w górnej części index.js , aby można było uzyskać dostęp do danych w naszej funkcji głównej.
const hotelData = require('./hotels.json');
Aby zaindeksować dane do indeksu wyszukiwania, musimy teraz utworzyć element SearchClient
.
SearchIndexClient
Element służy do tworzenia indeksu i zarządzania nim, SearchClient
ale służy do przekazywania dokumentów i wykonywania zapytań względem indeksu.
Istnieją dwa sposoby tworzenia elementu SearchClient
. Pierwszą opcją jest utworzenie od SearchClient
podstaw:
const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));
Alternatywnie możesz użyć getSearchClient()
metody , SearchIndexClient
aby utworzyć element SearchClient
:
const searchClient = indexClient.getSearchClient(indexName);
Teraz, gdy klient jest zdefiniowany, przekaż dokumenty do indeksu wyszukiwania. W takim przypadku używamy mergeOrUploadDocuments()
metody , która przekazuje dokumenty lub scala je z istniejącym dokumentem, jeśli dokument o tym samym kluczu już istnieje.
console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Przeszukiwanie indeksu
Po przekazaniu indeksu i przekazaniu dokumentów możesz wysyłać zapytania do indeksu. W tej sekcji wysyłamy pięć różnych zapytań do indeksu wyszukiwania, aby zademonstrować różne dostępne funkcje zapytań.
Zapytania są zapisywane w sendQueries()
funkcji, którą wywołujemy w funkcji main w następujący sposób:
await sendQueries(searchClient);
Zapytania są wysyłane przy użyciu search()
metody searchClient
. Pierwszy parametr to tekst wyszukiwania, a drugi parametr określa opcje wyszukiwania.
Przykład zapytania 1
Pierwsze zapytanie wyszukuje *
element , który jest odpowiednikiem wyszukiwania wszystkiego i wybiera trzy pola w indeksie. Jest to najlepsze rozwiązanie tylko select
dla potrzebnych pól, ponieważ ściąganie niepotrzebnych danych może powodować opóźnienie zapytań.
Dla searchOptions
tego zapytania ustawiono includeTotalCount
również wartość true
, która zwraca liczbę znalezionych pasujących wyników.
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
}
Pozostałe zapytania opisane poniżej należy również dodać do sendQueries()
funkcji. Są one tutaj oddzielone w celu czytelności.
Przykład zapytania 2
W następnym zapytaniu określamy termin "wifi"
wyszukiwania, a także uwzględniamy filtr, aby zwracać wyniki tylko wtedy, gdy stan jest równy 'FL'
. Wyniki są również uporządkowane przez hotel 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)}`);
}
Przykład zapytania 3
Następnie wyszukiwanie jest ograniczone do pojedynczego pola z możliwością wyszukiwania przy użyciu parametru searchFields
. Takie podejście jest doskonałym rozwiązaniem, aby zwiększyć wydajność zapytania, jeśli wiesz, że interesuje Cię tylko dopasowanie w niektórych polach.
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();
Przykład zapytania 4
Inną typową opcją uwzględnienia w zapytaniu jest facets
. Aspekty umożliwiają tworzenie filtrów w interfejsie użytkownika, aby ułatwić użytkownikom poznanie wartości, do których mogą filtrować.
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)}`);
}
Przykład zapytania 5
Ostatnie zapytanie używa getDocument()
metody searchClient
. Dzięki temu można efektywnie pobierać dokument przy użyciu jego klucza.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Podsumowanie zapytań
Poprzednie zapytania pokazują wiele sposobów dopasowywania terminów w zapytaniu: wyszukiwanie pełnotekstowe, filtry i autouzupełnianie.
Wyszukiwanie pełnotekstowe i filtry są wykonywane przy użyciu searchClient.search
metody . Zapytanie wyszukiwania można przekazać w searchText
ciągu, podczas gdy wyrażenie filtru może zostać przekazane we filter
właściwości SearchOptions
klasy. Aby filtrować bez wyszukiwania, wystarczy przekazać wartość "*" dla searchText
parametru search
metody . Aby wyszukać bez filtrowania, pozostaw filter
właściwość niezastawioną lub nie przekazuj SearchOptions
w ogóle wystąpienia.
W tym szybkim starcie użyjesz programu PowerShell i interfejsów API REST usługi Azure AI Search do tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania do wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten przewodnik szybkiego startu używa fikcyjnych danych hotelowych z azure-search-sample-data do wypełnienia indeksu.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę lub znajdź istniejącą usługę w bieżącej subskrypcji. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Azure CLI do uwierzytelniania bez klucza w Microsoft Entra ID.
Program PowerShell w wersji 7.3 lub nowszej. Ten szybki start używa polecenia Invoke-RestMethod do wykonywania wywołań API REST.
Konfigurowanie dostępu
Można nawiązać połączenie z usługą Azure AI Search przy użyciu kluczy API lub Microsoft Entra ID wraz z przypisaniami ról. Klucze są łatwiejsze do rozpoczęcia od, ale role są bezpieczniejsze.
Aby skonfigurować zalecany dostęp oparty na rolach:
Zaloguj się do witryny Azure Portal i wybierz usługę wyszukiwania.
W okienku po lewej stronie wybierz Ustawienia>Klucze.
W obszarze Kontrola dostępu do interfejsu API wybierz pozycję Oba.
Ta opcja umożliwia zarówno uwierzytelnianie oparte na kluczach, jak i bez klucza. Po przypisaniu ról możesz wrócić do tego kroku i wybrać pozycję Kontrola dostępu oparta na rolach.
W okienku po lewej stronie wybierz pozycję Kontrola dostępu (Zarządzanie dostępem i tożsamościami).
Wybierz Dodaj>Dodaj przypisanie roli.
Przypisz role Współautor usługi wyszukiwania i Współautor danych indeksu wyszukiwania do konta użytkownika.
Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobierz punkt końcowy
W następnej sekcji określisz następujący punkt końcowy, aby nawiązać połączenie z usługą Azure AI Search. W tych krokach przyjęto założenie, że skonfigurowano dostęp oparty na rolach.
Aby uzyskać punkt końcowy usługi:
Zaloguj się do witryny Azure Portal i wybierz usługę wyszukiwania.
W okienku po lewej stronie wybierz pozycję Przegląd.
Zanotuj adres URL, który powinien być podobny do
https://my-service.search.windows.net
.
Nawiązywanie połączenia z usługą Azure AI Search
Aby móc wykonywać wywołania interfejsu API REST do usługi Azure AI Search, musisz uwierzytelnić się i nawiązać połączenie z usługą. W programie PowerShell wykonasz następujące kroki, które obsługują polecenia interfejsu wiersza polecenia platformy Azure używane w krokach dwóch i trzech.
Aby nawiązać połączenie z usługą wyszukiwania:
W systemie lokalnym otwórz program PowerShell.
Zaloguj się do subskrypcji platformy Azure. Jeśli masz wiele subskrypcji, wybierz tę, która zawiera usługę wyszukiwania.
az login
Utwórz
$token
obiekt do przechowywania tokenu dostępu.$token = az account get-access-token --resource https://search.azure.com/ --query accessToken --output tsv
$headers
Utwórz obiekt do przechowywania tokenu i typu zawartości.$headers = @{ 'Authorization' = "Bearer $token" 'Content-Type' = 'application/json' 'Accept' = 'application/json' }
Musisz ustawić nagłówek tylko raz na sesję, ale musisz dodać go do każdego żądania.
$url
Utwórz obiekt przeznaczony dla kolekcji indeksów w usłudze wyszukiwania. Zastąp<YOUR-SEARCH-SERVICE>
wartością uzyskaną w funkcji Uzyskiwanie punktu końcowego.$url = "<YOUR-SEARCH-SERVICE>/indexes?api-version=2024-07-01&`$select=name"
Uruchom polecenie
Invoke-RestMethod
, aby wysłać żądanie GET do usługi wyszukiwania. DołączConvertTo-Json
, aby wyświetlić odpowiedzi z usługi.Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-Json
Jeśli usługa jest pusta i nie ma indeksów, odpowiedź jest podobna do poniższego przykładu. W przeciwnym razie zostanie wyświetlona reprezentacja definicji indeksu w formacie JSON.
{ "@odata.context": "https://my-service.search.windows.net/$metadata#indexes", "value": [ ] }
Tworzenie indeksu wyszukiwania
Przed dodaniem zawartości do usługi Azure AI Search należy utworzyć indeks, aby zdefiniować sposób przechowywania i struktury zawartości. Indeks jest koncepcyjnie podobny do tabeli w relacyjnej bazie danych, ale został specjalnie zaprojektowany pod kątem operacji wyszukiwania, takich jak wyszukiwanie pełnotekstowe.
Uruchom następujące polecenia w tej samej sesji programu PowerShell, która została uruchomiona w poprzedniej sekcji.
Aby utworzyć indeks:
Stwórz obiekt
$body
do zdefiniowania schematu indeksu.$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} ] } ] } "@
Zaktualizuj obiekt,
$url
aby był przeznaczony dla nowego indeksu. Zastąp<YOUR-SEARCH-SERVICE>
wartością uzyskaną w funkcji Uzyskiwanie punktu końcowego.$url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart?api-version=2024-07-01"
Uruchom polecenie
Invoke-RestMethod
, aby utworzyć indeks w usłudze wyszukiwania.Invoke-RestMethod -Uri $url -Headers $headers -Method Put -Body $body | ConvertTo-Json
Odpowiedź powinna zawierać reprezentację JSON schematu indeksu.
Informacje o żądaniu tworzenia indeksu
Ten szybki start wywołuje Indeksy - Tworzenie (interfejs API REST) aby utworzyć indeks wyszukiwania o nazwie hotels-quickstart
i jego fizycznych struktur danych w usłudze wyszukiwania.
W schemacie indeksu, kolekcja fields
definiuje strukturę dokumentów hotelowych. Każde pole ma name
, dane type
i atrybuty, które określają jego zachowanie podczas indeksowania i zapytań. Pole HotelId
jest oznaczone jako klucz, którego usługa Azure AI Search wymaga unikatowego identyfikowania każdego dokumentu w indeksie.
Kluczowe kwestie dotyczące schematu indeksu:
Użyj pól ciągu (
Edm.String
), aby umożliwić wyszukiwanie pełnotekstowe danych liczbowych. Inne obsługiwane typy danych, takie jakEdm.Int32
, są filtrowalne, sortowalne, ustawialne jako facety i możliwe do pobrania, ale nie da się ich przeszukiwać.Większość naszych pól to proste typy danych, ale można zdefiniować złożone typy reprezentujące zagnieżdżone dane, takie jak
Address
pole.Atrybuty pól określają dozwolone akcje. Interfejsy API REST domyślnie zezwalają na wiele akcji. Na przykład wszystkie ciągi można wyszukiwać i pobierać. W przypadku interfejsów API REST można używać atrybutów tylko wtedy, gdy trzeba wyłączyć zachowanie.
Ładowanie indeksu
Nowo utworzone indeksy są puste. Aby wypełnić indeks i umożliwić wyszukiwanie, należy przekazać dokumenty JSON zgodne ze schematem indeksu.
W usłudze Azure AI Search dokumenty służą zarówno jako dane wejściowe do indeksowania, jak i danych wyjściowych zapytań. Dla uproszczenia ten przewodnik szybkiego startu zawiera przykładowe dokumenty hotelowe jako inline JSON. Jednak w scenariuszach produkcyjnych zawartość jest często pobierana z połączonych źródeł danych i przekształcana w format JSON przy użyciu indeksatorów.
Aby załadować dokumenty do swojego indeksu:
$body
Utwórz obiekt do przechowywania ładunku JSON czterech przykładowych dokumentów.$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" } } ] } "@
$url
Zaktualizuj obiekt, aby był przeznaczony dla punktu końcowego indeksowania. Zastąp<YOUR-SEARCH-SERVICE>
wartością uzyskaną w funkcji Uzyskiwanie punktu końcowego.$url = "<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs/index?api-version=2024-07-01"
Uruchom
Invoke-RestMethod
, aby wysłać żądanie przesłania do usługi wyszukiwania.Invoke-RestMethod -Uri $url -Headers $headers -Method Post -Body $body | ConvertTo-Json
Odpowiedź powinna zawierać klucz i stan każdego przekazanego dokumentu.
Informacje o żądaniu ładowania
W tym przewodniku Szybki start wywoływane są dokumenty — indeks (interfejs API REST), aby dodać do indeksu cztery przykładowe dokumenty hotelowe. W porównaniu z poprzednim żądaniem URI jest rozszerzony, aby uwzględniać kolekcję docs
i operację index
.
Każdy dokument w tablicy value
reprezentuje hotel i zawiera pola zgodne ze schematem indeksu. Parametr @search.action
określa operację do wykonania dla każdego dokumentu. W naszym przykładzie użyto elementu upload
, który dodaje dokument, jeśli nie istnieje lub aktualizuje dokument, jeśli istnieje.
Wykonywanie zapytań względem indeksu
Teraz, gdy dokumenty są ładowane do indeksu, możesz użyć wyszukiwania pełnotekstowego, aby znaleźć określone terminy lub frazy w swoich polach.
Aby uruchomić zapytanie pełnotekstowe względem indeksu:
Zaktualizuj obiekt,
$url
aby określić parametry wyszukiwania. Zastąp<YOUR-SEARCH-SERVICE>
wartością uzyskaną w funkcji Uzyskiwanie punktu końcowego.$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=attached restaurant&searchFields=Description,Tags&$select=HotelId,HotelName,Tags,Description&$count=true'
Uruchom polecenie
Invoke-RestMethod
, aby wysłać żądanie zapytania do usługi wyszukiwania.Invoke-RestMethod -Uri $url -Headers $headers | ConvertTo-Json
Odpowiedź powinna być podobna do poniższego przykładu, która pokazuje jeden pasujący dokument hotelowy, jego wynik istotności i wybrane pola.
{ "@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" } ] }
Informacje o żądaniu zapytania
Ta instrukcja szybkiego startu wywołuje metodę POST wyszukiwania w interfejsie API REST, aby znaleźć dokumenty hotelowe spełniające kryteria wyszukiwania. Identyfikator URI nadal jest przeznaczony dla docs
kolekcji, ale już nie zawiera operacji index
.
Żądania wyszukiwania pełnotekstowego search
zawsze zawierają parametr zawierający tekst zapytania. Tekst zapytania może zawierać co najmniej jeden termin, frazy lub operatory. Oprócz search
, można określić inne parametry, aby uściślić zachowanie wyszukiwania i wyniki.
Nasze zapytanie wyszukuje terminy "przyłączona restauracja" w polach Description
i Tags
każdego dokumentu hotelowego. Parametr $select
ogranicza pola zwrócone w odpowiedzi do HotelId
, HotelName
, Tags
i Description
. Parametr $count
żąda całkowitej liczby pasujących dokumentów.
Inne przykłady zapytań
Uruchom następujące polecenia, aby zapoznać się ze składnią zapytania. Możesz wykonywać wyszukiwania ciągów, używać $filter
wyrażeń, ograniczać zestawy wyników, wybierać określone pola i nie tylko. Pamiętaj, aby zastąpić <YOUR-SEARCH-SERVICE>
wartością uzyskaną w Pobierz punkt końcowy.
# Query example 1
# Search the index for the terms 'restaurant' and 'wifi'
# Return only the HotelName, Description, and Tags fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=restaurant wifi&$count=true&$select=HotelName,Description,Tags'
# Query example 2
# Use a filter to find hotels rated 4 or higher
# Return only the HotelName and Rating fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=*&$filter=Rating gt 4&$select=HotelName,Rating'
# Query example 3
# Take the top two results
# Return only the HotelName and Category fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=boutique&$top=2&$select=HotelName,Category'
# Query example 4
# Sort by a specific field (Address/City) in ascending order
# Return only the HotelName, Address/City, Tags, and Rating fields
$url = '<YOUR-SEARCH-SERVICE>/indexes/hotels-quickstart/docs?api-version=2024-07-01&search=pool&$orderby=Address/City asc&$select=HotelName, Address/City, Tags, Rating'
W tym przewodniku szybkiego startu użyjesz biblioteki klienta Azure.Search.Documents do tworzenia, ładowania i wykonywania zapytań względem indeksu wyszukiwania z przykładowymi danymi dla wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
W tym przewodniku Quickstart używane są fikcyjne dane hotelowe z repozytorium azure-search-sample-data w celu zasilenia indeksu.
Napiwek
Możesz pobrać i uruchomić gotowy notes.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę , jeśli jej nie masz. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Program Visual Studio Code z rozszerzeniem języka Python lub równoważnym środowiskiem IDE w języku Python w wersji 3.10 lub nowszej. Jeśli nie zainstalowano odpowiedniej wersji języka Python, postępuj zgodnie z instrukcjami w samouczku języka Python programu VS Code.
Wymagania wstępne dotyczące identyfikatora entra firmy Microsoft
W przypadku zalecanego uwierzytelniania bez klucza za pomocą identyfikatora Entra firmy Microsoft należy:
Zainstaluj interfejs wiersza polecenia platformy Azure.
Przypisz role
Search Service Contributor
iSearch Index Data Contributor
do swojego konta użytkownika. Role można przypisać w witrynie Azure Portal w obszarze Kontrola dostępu (IAM)>Dodawanie przypisania roli. Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobieranie informacji o zasobie
Aby uwierzytelnić aplikację przy użyciu usługi Azure AI usługa wyszukiwania, należy pobrać następujące informacje:
Nazwa zmiennej | Wartość |
---|---|
SEARCH_API_ENDPOINT |
Tę wartość można znaleźć w witrynie Azure Portal. Wybierz usługę wyszukiwania, a następnie z menu po lewej stronie wybierz pozycję Przegląd. Wartość adresu URL w obszarze Podstawy to potrzebny punkt końcowy. Przykładowy punkt końcowy może wyglądać podobnie jak https://mydemo.search.windows.net . |
Dowiedz się więcej na temat uwierzytelniania bez klucza i ustawiania zmiennych środowiskowych.
Konfigurowanie środowiska
Przykładowy kod jest uruchamiany w notesie Jupyter. Dlatego należy skonfigurować środowisko do uruchamiania notesów Jupyter.
Pobierz lub skopiuj przykładowy notes z usługi GitHub.
Otwórz notes w programie Visual Studio Code.
Utwórz nowe środowisko języka Python, które ma być używane do instalowania pakietów potrzebnych na potrzeby tego samouczka.
Ważne
Nie instaluj pakietów w globalnej instalacji języka Python. Zawsze należy używać środowiska wirtualnego lub conda podczas instalowania pakietów języka Python. W przeciwnym razie możesz przerwać globalną instalację języka Python.
Skonfigurowanie może potrwać minutę. Jeśli wystąpią problemy, zobacz Środowiska języka Python w programie VS Code.
Zainstaluj notesy Jupyter i jądro IPython dla notesów Jupyter, jeśli jeszcze ich nie masz.
pip install jupyter pip install ipykernel python -m ipykernel install --user --name=.venv
Wybierz jądro notesu.
- W prawym górnym rogu notesu wybierz pozycję Wybierz jądro.
- Jeśli widzisz
.venv
ją na liście, wybierz ją. Jeśli go nie widzisz, wybierz pozycję
Tworzenie, ładowanie i wykonywanie zapytań względem indeksu wyszukiwania
W tej sekcji dodasz kod, aby utworzyć indeks wyszukiwania, załadować go przy użyciu dokumentów i uruchomić zapytania. Uruchom program, aby wyświetlić wyniki w konsoli programu . Aby uzyskać szczegółowe wyjaśnienie kodu, zobacz sekcję wyjaśniającą kod .
Upewnij się, że notes jest otwarty w
.venv
jądrze zgodnie z opisem w poprzedniej sekcji.Uruchom pierwszą komórkę kodu, aby zainstalować wymagane pakiety, w tym azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet ! pip install azure-identity --quiet ! pip install python-dotenv --quiet
Zastąp zawartość drugiej komórki kodu następującym kodem w zależności od metody uwierzytelniania.
Uwaga
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić
DefaultAzureCredential
obiekt obiektemAzureKeyCredential
.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"
Usuń następujące dwa wiersze z komórki Tworzenie kodu indeksu . Poświadczenia są już ustawione w poprzedniej komórce kodu.
from azure.core.credentials import AzureKeyCredential credential = AzureKeyCredential(search_api_key)
Uruchom komórkę Tworzenie kodu indeksu , aby utworzyć indeks wyszukiwania.
Uruchom pozostałe komórki kodu sekwencyjnie, aby załadować dokumenty i uruchomić zapytania.
Wyjaśnienie kodu
Tworzenie indeksu
SearchIndexClient
służy do tworzenia indeksów usługi Azure AI Search i zarządzania nimi. Każde pole jest identyfikowane przez element name
i ma określony element type
.
Każde pole ma również szereg atrybutów indeksu, które określają, czy usługa Azure AI Search może wyszukiwać, filtrować, sortować i aspekty po polu. Większość pól to proste typy danych, ale niektóre, takie jak AddressType
typy złożone, które umożliwiają tworzenie rozbudowanych struktur danych w indeksie. Więcej informacji na temat obsługiwanych typów danych i atrybutów indeksu opisano w artykule Create Index (REST) (Tworzenie indeksu (REST).
Tworzenie ładunku dokumentów i przekazywanie dokumentów
Użyj akcji indeksu dla typu operacji, takiej jak przekazywanie lub scalanie i przekazywanie. Dokumenty pochodzą z przykładu HotelsData w usłudze GitHub.
Przeszukiwanie indeksu
Wyniki zapytania można uzyskać zaraz po indeksowanym pierwszym dokumencie, ale rzeczywiste testowanie indeksu powinno poczekać, aż wszystkie dokumenty zostaną zindeksowane.
Użyj metody wyszukiwania klasy search.client.
Przykładowe zapytania w notesie to:
- Zapytanie podstawowe: wykonuje puste wyszukiwanie (
search=*
), zwracając nies rankingową listę (wynik wyszukiwania = 1,0) dowolnych dokumentów. Ponieważ nie ma żadnych kryteriów, wszystkie dokumenty są uwzględniane w wynikach. - Zapytanie terminu: dodaje całe terminy do wyrażenia wyszukiwania ("wifi"). To zapytanie określa, że wyniki zawierają tylko te pola w instrukcji
select
. Ograniczenie pól, które wracają, minimalizuje ilość danych wysyłanych z powrotem przez sieć i zmniejsza opóźnienie wyszukiwania. - Zapytanie filtrowane: dodaj wyrażenie filtru, zwracając tylko te hotele z oceną większą niż cztery posortowane w kolejności malejącej.
- Określanie zakresu pól: dodaj
search_fields
do zakresu wykonywania zapytań do określonych pól. - Aspekty: Generuj aspekty dla pozytywnych dopasowań znalezionych w wynikach wyszukiwania. Brak dopasowań zerowych. Jeśli wyniki wyszukiwania nie zawierają terminu wifi, sieć Wi-Fi nie jest wyświetlana w strukturze nawigacji aspektowej.
- Wyszukaj dokument: Zwróć dokument na podstawie jego klucza. Ta operacja jest przydatna, jeśli chcesz podać przeglądanie szczegółowe, gdy użytkownik wybierze element w wynikach wyszukiwania.
- Autouzupełnianie: podaj potencjalne dopasowania jako typy użytkowników w polu wyszukiwania. Autouzupełnianie używa sugestora (
sg
), aby wiedzieć, które pola zawierają potencjalne dopasowania do żądań sugestora. W tym przewodniku Szybki start te pola toTags
: ,Address/City
Address/Country
. Aby symulować autouzupełnianie, przekaż litery sa jako ciąg częściowy. Metoda autouzupełniania elementu SearchClient wysyła potencjalne dopasowania terminów.
Usuwanie indeksu
Jeśli skończysz z tym indeksem, możesz go usunąć, uruchamiając komórkę Wyczyść kod. Usunięcie niepotrzebnych indeksów zwalnia miejsce na przechodzenie przez kolejne przewodniki Szybki start i samouczki.
W tym szybkim przewodniku użyjesz interfejsów API REST usługi Azure AI Search do tworzenia indeksu wyszukiwania, jego ładowania i wykonywania zapytań na potrzeby wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten szybki przewodnik używa fikcyjnych danych hotelowych z repozytorium azure-search-sample-data do wypełnienia indeksu.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę lub znajdź istniejącą usługę w bieżącej subskrypcji. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Azure CLI do uwierzytelniania bez klucza w Microsoft Entra ID.
Konfigurowanie dostępu
Możesz nawiązać połączenie z usługą Azure AI Search przy użyciu kluczy API lub Microsoft Entra ID z przypisanymi rolami. Klucze są łatwiejsze do rozpoczęcia od, ale role są bezpieczniejsze.
Aby skonfigurować zalecany dostęp oparty na rolach:
Zaloguj się do witryny Azure Portal i wybierz usługę wyszukiwania.
W okienku po lewej stronie wybierz Ustawienia>Klucze.
W obszarze Kontrola dostępu do interfejsu API wybierz pozycję Oba.
Ta opcja umożliwia zarówno uwierzytelnianie oparte na kluczach, jak i bez klucza. Po przypisaniu ról możesz wrócić do tego kroku i wybrać pozycję Kontrola dostępu oparta na rolach.
W okienku po lewej stronie wybierz pozycję Kontrola dostępu (Zarządzanie dostępem i tożsamościami).
Wybierz Dodaj>Dodaj przypisanie roli.
Przypisz role Współautor usługi wyszukiwania i Współautor danych indeksu wyszukiwania do konta użytkownika.
Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Uzyskiwanie punktu końcowego i tokenu
W następnej sekcji określisz następujący punkt końcowy i token, aby nawiązać połączenie z usługą Azure AI Search. W tych krokach przyjęto założenie, że skonfigurowano dostęp oparty na rolach.
Aby uzyskać punkt końcowy i token usługi:
Zaloguj się do witryny Azure Portal i wybierz usługę wyszukiwania.
W okienku po lewej stronie wybierz pozycję Przegląd.
Zanotuj adres URL, który powinien być podobny do
https://my-service.search.windows.net
.W systemie lokalnym otwórz terminal.
Zaloguj się do subskrypcji platformy Azure. Jeśli masz wiele subskrypcji, wybierz tę, która zawiera usługę wyszukiwania.
az login
Zanotuj token Microsoft Entra.
az account get-access-token --scope https://search.azure.com/.default
Skonfiguruj swój plik
Aby móc wykonywać wywołania interfejsu API REST do usługi Azure AI Search, należy utworzyć plik do przechowywania punktu końcowego usługi, tokenu uwierzytelniania oraz przyszłych żądań. Rozszerzenie klienta REST w programie Visual Studio Code obsługuje to zadanie.
Aby skonfigurować plik żądania:
W systemie lokalnym otwórz program Visual Studio Code.
Utwórz plik
.rest
lub.http
.Wklej następujące symbole zastępcze i żądanie do pliku.
@baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE @token = PUT-YOUR-PERSONAL-IDENTITY-TOKEN-HERE ### List existing indexes by name GET {{baseUrl}}/indexes?api-version=2024-07-01 HTTP/1.1 Authorization: Bearer {{token}}
Zastąp symbole zastępcze
@baseUrl
i@token
wartościami uzyskanymi w sekcji Uzyskiwanie punktu końcowego i tokenu. Nie należy stosować znaków cudzysłowu.W obszarze
### List existing indexes by name
wybierz pozycję Wyślij żądanie.Odpowiedź powinna pojawić się w sąsiednim okienku. Jeśli masz istniejące indeksy, są one wyświetlane. W przeciwnym razie lista jest pusta. Jeśli kod HTTP to
200 OK
, możesz przystąpić do następnych kroków.
Tworzenie indeksu wyszukiwania
Przed dodaniem zawartości do usługi Azure AI Search należy utworzyć indeks, aby zdefiniować sposób przechowywania i struktury zawartości. Indeks jest koncepcyjnie podobny do tabeli w relacyjnej bazie danych, ale został specjalnie zaprojektowany pod kątem operacji wyszukiwania, takich jak wyszukiwanie pełnotekstowe.
Aby utworzyć indeks:
Wklej następujące żądanie do pliku.
### Create a new index POST {{baseUrl}}/indexes?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json Authorization: Bearer {{token}} { "name": "hotels-quickstart", "fields": [ {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true}, {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false}, {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"}, {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}, {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true}, {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true}, {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true}, {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true}, {"name": "Address", "type": "Edm.ComplexType", "fields": [ {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true}, {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}, {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}, {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}, {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true} ] } ] }
W obszarze
### Create a new index
wybierz pozycję Wyślij żądanie.Powinieneś otrzymać odpowiedź
HTTP/1.1 201 Created
, której treść zawiera JSON-ową reprezentację schematu indeksu.
Informacje o żądaniu tworzenia indeksu
Ten szybki start wywołuje Indeksy - Tworzenie (interfejs API REST) aby utworzyć indeks wyszukiwania o nazwie hotels-quickstart
i jego fizycznych struktur danych w usłudze wyszukiwania.
W schemacie indeksu, kolekcja fields
definiuje strukturę dokumentów hotelowych. Każde pole ma name
, dane type
i atrybuty, które określają jego zachowanie podczas indeksowania i zapytań. Pole HotelId
jest oznaczone jako klucz, którego usługa Azure AI Search wymaga unikatowego identyfikowania każdego dokumentu w indeksie.
Kluczowe kwestie dotyczące schematu indeksu:
Użyj pól ciągu (
Edm.String
), aby umożliwić wyszukiwanie pełnotekstowe danych liczbowych. Inne obsługiwane typy danych, takie jakEdm.Int32
, są filtrowalne, sortowalne, ustawialne jako facety i możliwe do pobrania, ale nie da się ich przeszukiwać.Większość naszych pól to proste typy danych, ale można zdefiniować złożone typy reprezentujące zagnieżdżone dane, takie jak
Address
pole.Atrybuty pól określają dozwolone akcje. Interfejsy API REST domyślnie zezwalają na wiele akcji. Na przykład wszystkie ciągi można wyszukiwać i pobierać. W przypadku interfejsów API REST można używać atrybutów tylko wtedy, gdy trzeba wyłączyć zachowanie.
Ładowanie indeksu
Nowo utworzone indeksy są puste. Aby wypełnić indeks i umożliwić wyszukiwanie, należy przekazać dokumenty JSON zgodne ze schematem indeksu.
W usłudze Azure AI Search dokumenty służą zarówno jako dane wejściowe do indeksowania, jak i danych wyjściowych zapytań. Dla uproszczenia ten przewodnik szybkiego startu zawiera przykładowe dokumenty hotelowe jako inline JSON. Jednak w scenariuszach produkcyjnych zawartość jest często pobierana z połączonych źródeł danych i przekształcana w format JSON przy użyciu indeksatorów.
Aby załadować dokumenty do swojego indeksu:
Wklej następujące żądanie do pliku.
### Upload documents POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json Authorization: Bearer {{token}} { "value": [ { "@search.action": "upload", "HotelId": "1", "HotelName": "Stay-Kay City Hotel", "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", "Category": "Boutique", "Tags": [ "view", "air conditioning", "concierge" ], "ParkingIncluded": false, "LastRenovationDate": "2022-01-18T00:00:00Z", "Rating": 3.60, "Address": { "StreetAddress": "677 5th Ave", "City": "New York", "StateProvince": "NY", "PostalCode": "10022", "Country": "USA" } }, { "@search.action": "upload", "HotelId": "2", "HotelName": "Old Century Hotel", "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.", "Category": "Boutique", "Tags": [ "pool", "free wifi", "concierge" ], "ParkingIncluded": false, "LastRenovationDate": "2019-02-18T00:00:00Z", "Rating": 3.60, "Address": { "StreetAddress": "140 University Town Center Dr", "City": "Sarasota", "StateProvince": "FL", "PostalCode": "34243", "Country": "USA" } }, { "@search.action": "upload", "HotelId": "3", "HotelName": "Gastronomic Landscape Hotel", "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.", "Category": "Suite", "Tags": [ "restaurant", "bar", "continental breakfast" ], "ParkingIncluded": true, "LastRenovationDate": "2015-09-20T00:00:00Z", "Rating": 4.80, "Address": { "StreetAddress": "3393 Peachtree Rd", "City": "Atlanta", "StateProvince": "GA", "PostalCode": "30326", "Country": "USA" } }, { "@search.action": "upload", "HotelId": "4", "HotelName": "Sublime Palace Hotel", "Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 19th century resort, updated for every modern convenience.", "Category": "Luxury", "Tags": [ "concierge", "view", "air conditioning" ], "ParkingIncluded": true, "LastRenovationDate": "2020-02-06T00:00:00Z", "Rating": 4.60, "Address": { "StreetAddress": "7400 San Pedro Ave", "City": "San Antonio", "StateProvince": "TX", "PostalCode": "78216", "Country": "USA" } } ] }
W obszarze
### Upload documents
wybierz pozycję Wyślij żądanie.Powinna zostać otrzymana
HTTP/1.1 200 OK
odpowiedź, której treść zawiera klucz i stan każdego przekazanego dokumentu.
Informacje o żądaniu ładowania
W tym przewodniku Szybki start wywoływane są dokumenty — indeks (interfejs API REST), aby dodać do indeksu cztery przykładowe dokumenty hotelowe. W porównaniu z poprzednim żądaniem URI jest rozszerzony, aby uwzględniać kolekcję docs
i operację index
.
Każdy dokument w tablicy value
reprezentuje hotel i zawiera pola zgodne ze schematem indeksu. Parametr @search.action
określa operację do wykonania dla każdego dokumentu. W naszym przykładzie użyto elementu upload
, który dodaje dokument, jeśli nie istnieje lub aktualizuje dokument, jeśli istnieje.
Wykonywanie zapytań względem indeksu
Teraz, gdy dokumenty są ładowane do indeksu, możesz użyć wyszukiwania pełnotekstowego, aby znaleźć określone terminy lub frazy w swoich polach.
Aby uruchomić zapytanie pełnotekstowe względem indeksu:
Wklej następujące żądanie do pliku.
### Run a query POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version=2024-07-01 HTTP/1.1 Content-Type: application/json Authorization: Bearer {{token}} { "search": "attached restaurant", "select": "HotelId, HotelName, Tags, Description", "searchFields": "Description, Tags", "count": true }
W obszarze
### Run a query
wybierz pozycję Wyślij żądanie.Powinieneś otrzymać odpowiedź
HTTP/1.1 200 OK
podobną do poniższego przykładu, która pokazuje jeden pasujący dokument hotelowy, jego wynik istotności i wybrane pola.{ "@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" ] } ] }
Informacje o żądaniu zapytania
Ta instrukcja szybkiego startu wywołuje metodę POST wyszukiwania w interfejsie API REST, aby znaleźć dokumenty hotelowe spełniające kryteria wyszukiwania. Identyfikator URI jest teraz przeznaczony dla /docs/search
operacji.
Żądania wyszukiwania pełnotekstowego search
zawsze zawierają parametr zawierający tekst zapytania. Tekst zapytania może zawierać co najmniej jeden termin, frazy lub operatory. Oprócz search
możesz określić inne parametry, aby uściślić wyniki wyszukiwania i jego zachowanie.
Nasze zapytanie wyszukuje terminy "restauracja na miejscu" w polach Description
i Tags
każdego dokumentu hotelowego. Parametr select
ogranicza pola zwrócone w odpowiedzi do HotelId
, HotelName
, Tags
i Description
. Parametr count
żąda całkowitej liczby pasujących dokumentów.
W tym szybkim starcie użyjesz biblioteki klienta Azure.Search.Documents do tworzenia, ładowania i wykonywania zapytań do indeksu wyszukiwania z przykładowymi danymi na potrzeby wyszukiwania pełnotekstowego. Wyszukiwanie pełnotekstowe używa platformy Apache Lucene do indeksowania i zapytań oraz algorytmu klasyfikacji BM25 na potrzeby oceniania wyników.
Ten szybki start używa fikcyjnych danych hotelowych z repozytorium azure-search-sample-data w celu wypełnienia indeksu.
Napiwek
Możesz pobrać kod źródłowy , aby rozpocząć od ukończonego projektu lub wykonać następujące kroki, aby utworzyć własny.
Wymagania wstępne
- Konto Azure z aktywną subskrypcją. Utwórz konto bezpłatnie.
- Usługa wyszukiwania sztucznej inteligencji platformy Azure. Utwórz usługę , jeśli jej nie masz. Możesz skorzystać z bezpłatnej usługi w ramach szybkiego startu.
Wymagania wstępne dotyczące identyfikatora entra firmy Microsoft
W przypadku zalecanego uwierzytelniania bez klucza za pomocą identyfikatora Entra firmy Microsoft należy:
Zainstaluj interfejs wiersza polecenia platformy Azure.
Przypisz role
Search Service Contributor
iSearch Index Data Contributor
do swojego konta użytkownika. Role można przypisać w witrynie Azure Portal w obszarze Kontrola dostępu (IAM)>Dodawanie przypisania roli. Aby uzyskać więcej informacji, zobacz Nawiązywanie połączenia z usługą Azure AI Search przy użyciu ról.
Pobieranie informacji o zasobie
Aby uwierzytelnić aplikację przy użyciu usługi Azure AI usługa wyszukiwania, należy pobrać następujące informacje:
Nazwa zmiennej | Wartość |
---|---|
SEARCH_API_ENDPOINT |
Tę wartość można znaleźć w witrynie Azure Portal. Wybierz usługę wyszukiwania, a następnie z menu po lewej stronie wybierz pozycję Przegląd. Wartość adresu URL w obszarze Podstawy to potrzebny punkt końcowy. Przykładowy punkt końcowy może wyglądać podobnie jak https://mydemo.search.windows.net . |
Dowiedz się więcej na temat uwierzytelniania bez klucza i ustawiania zmiennych środowiskowych.
Konfiguruj
Utwórz nowy folder
full-text-quickstart
zawierający aplikację i otwórz program Visual Studio Code w tym folderze za pomocą następującego polecenia:mkdir full-text-quickstart && cd full-text-quickstart
Utwórz element
package.json
za pomocą następującego polecenia:npm init -y
Zaktualizuj element do ecMAScript
package.json
za pomocą następującego polecenia:npm pkg set type=module
Zainstaluj bibliotekę klienta usługi Azure AI Search (Azure.Search.Documents) dla języka JavaScript za pomocą następujących elementów:
npm install @azure/search-documents
W przypadku zalecanego uwierzytelniania bez hasła zainstaluj bibliotekę klienta tożsamości platformy Azure za pomocą polecenia:
npm install @azure/identity
Tworzenie, ładowanie i wykonywanie zapytań względem indeksu wyszukiwania
W poprzedniej sekcji konfiguracji zainstalowano bibliotekę klienta usługi Azure AI Search i inne zależności.
W tej sekcji dodasz kod, aby utworzyć indeks wyszukiwania, załadować go przy użyciu dokumentów i uruchomić zapytania. Uruchom program, aby wyświetlić wyniki w konsoli programu . Aby uzyskać szczegółowe wyjaśnienie kodu, zobacz sekcję wyjaśniającą kod .
Przykładowy kod w tym przewodniku Szybki start używa identyfikatora Entra firmy Microsoft do zalecanego uwierzytelniania bez klucza. Jeśli wolisz użyć klucza interfejsu API, możesz zastąpić DefaultAzureCredential
obiekt obiektem AzureKeyCredential
.
const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
Utwórz nowy plik o nazwie index.ts i wklej następujący kod do 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); });
Utwórz plik o nazwie hotels.json i wklej następujący kod do 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" } } ] }
Utwórz plik do
tsconfig.json
transpilowania kodu TypeScript i skopiuj następujący kod dla języka 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"] }
Transpiluj z języka TypeScript do języka JavaScript.
tsc
Zaloguj się do platformy Azure przy użyciu następującego polecenia:
az login
Uruchom kod JavaScript za pomocą następującego polecenia:
node index.js
Wyjaśnienie kodu
tworzenie indeksu
Utwórz plik hotels_quickstart_index.json. Ten plik definiuje sposób działania usługi Azure AI Search z dokumentami ładowanymi w następnym kroku. Każde pole jest identyfikowane przez element name
i ma określony element type
. Każde pole ma również szereg atrybutów indeksu, które określają, czy usługa Azure AI Search może wyszukiwać, filtrować, sortować i aspekty po polu. Większość pól to proste typy danych, ale niektóre, takie jak AddressType
typy złożone, które umożliwiają tworzenie rozbudowanych struktur danych w indeksie. Więcej informacji na temat obsługiwanych typów danych i atrybutów indeksu opisano w artykule Create Index (REST) (Tworzenie indeksu (REST).
Chcemy zaimportować hotels_quickstart_index.json , aby funkcja main mogła uzyskać dostęp do definicji indeksu.
import indexDefinition from './hotels_quickstart_index.json';
interface HotelIndexDefinition {
name: string;
fields: SimpleField[] | ComplexField[];
suggesters: SearchSuggester[];
};
const hotelIndexDefinition: HotelIndexDefinition = indexDefinition as HotelIndexDefinition;
W ramach funkcji main utworzymy element SearchIndexClient
, który służy do tworzenia indeksów usługi Azure AI Search i zarządzania nimi.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Następnie chcemy usunąć indeks, jeśli już istnieje. Ta operacja jest powszechną praktyką w przypadku kodu testowego/demonstracyjnego.
Robimy to, definiując prostą funkcję, która próbuje usunąć indeks.
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.');
}
}
Aby uruchomić funkcję, wyodrębniamy nazwę indeksu z definicji indeksu i przekazujemy indexName
element wraz z funkcją indexClient
deleteIndexIfExists()
.
// Getting the name of the index from the index definition
const indexName: string = hotelIndexDefinition.name;
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Następnie możemy utworzyć indeks za pomocą createIndex()
metody .
console.log('Creating index...');
let index = await indexClient.createIndex(hotelIndexDefinition);
console.log(`Index named ${index.name} has been created.`);
Ładowanie dokumentów
W usłudze Azure AI Search dokumenty to struktury danych, które są danymi wejściowymi do indeksowania i danych wyjściowych z zapytań. Możesz wypchnąć takie dane do indeksu lub użyć indeksatora. W takim przypadku programowo wypchniemy dokumenty do indeksu.
Dane wejściowe dokumentu mogą być wierszami w bazie danych, obiektach blob w usłudze Blob Storage lub, jak w tym przykładzie, dokumentach JSON na dysku. Możesz pobrać hotels.json lub utworzyć własny plik hotels.json z następującą zawartością:
Podobnie jak w przypadku elementu indexDefinition, musimy również zaimportować hotels.json
w górnej części index.ts , aby można było uzyskać dostęp do danych w naszej funkcji main.
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"];
Aby zaindeksować dane do indeksu wyszukiwania, musimy teraz utworzyć element SearchClient
.
SearchIndexClient
Element służy do tworzenia indeksu i zarządzania nim, SearchClient
ale służy do przekazywania dokumentów i wykonywania zapytań względem indeksu.
Istnieją dwa sposoby tworzenia elementu SearchClient
. Pierwszą opcją jest utworzenie od SearchClient
podstaw:
const searchClient = new SearchClient<Hotel>(endpoint, indexName, new AzureKeyCredential(apiKey));
Alternatywnie możesz użyć getSearchClient()
metody , SearchIndexClient
aby utworzyć element SearchClient
:
const searchClient = indexClient.getSearchClient<Hotel>(indexName);
Teraz, gdy klient jest zdefiniowany, przekaż dokumenty do indeksu wyszukiwania. W takim przypadku używamy mergeOrUploadDocuments()
metody , która przekazuje dokumenty lub scala je z istniejącym dokumentem, jeśli dokument o tym samym kluczu już istnieje. Następnie sprawdź, czy operacja zakończyła się pomyślnie, ponieważ istnieje co najmniej pierwszy dokument.
console.log("Uploading documents...");
const indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotels);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Uruchom ponownie program za pomocą polecenia tsc && node index.ts
. W kroku 1 powinien zostać wyświetlony nieco inny zestaw komunikatów. Tym razem indeks istnieje i powinien zostać wyświetlony komunikat o usunięciu go, zanim aplikacja utworzy nowy indeks i opublikuje do niego dane.
Przed uruchomieniem zapytań w następnym kroku zdefiniuj funkcję, aby program czekał na jedną sekundę. Odbywa się to tylko w celach testowych/demonstracyjnych, aby upewnić się, że indeksowanie zakończy się i że dokumenty są dostępne w indeksie dla naszych zapytań.
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Aby program czekał na jedną sekundę, wywołaj sleep
funkcję:
sleep(1000);
Przeszukiwanie indeksu
Po przekazaniu indeksu i przekazaniu dokumentów możesz wysyłać zapytania do indeksu. W tej sekcji wysyłamy pięć różnych zapytań do indeksu wyszukiwania, aby zademonstrować różne dostępne funkcje zapytań.
Zapytania są zapisywane w sendQueries()
funkcji, którą wywołujemy w funkcji main w następujący sposób:
await sendQueries(searchClient);
Zapytania są wysyłane przy użyciu search()
metody searchClient
. Pierwszy parametr to tekst wyszukiwania, a drugi parametr określa opcje wyszukiwania.
Przykład zapytania 1
Pierwsze zapytanie wyszukuje *
element , który jest odpowiednikiem wyszukiwania wszystkiego i wybiera trzy pola w indeksie. Jest to najlepsze rozwiązanie tylko select
dla potrzebnych pól, ponieważ ściąganie niepotrzebnych danych może powodować opóźnienie zapytań.
Dla searchOptions
tego zapytania ustawiono includeTotalCount
również wartość true
, która zwróci liczbę znalezionych pasujących wyników.
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
}
Pozostałe zapytania opisane poniżej należy również dodać do sendQueries()
funkcji. Są one tutaj oddzielone w celu czytelności.
Przykład zapytania 2
W następnym zapytaniu określamy termin "wifi"
wyszukiwania, a także uwzględniamy filtr, aby zwracać wyniki tylko wtedy, gdy stan jest równy 'FL'
. Wyniki są również uporządkowane przez hotel 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)}`);
}
Przykład zapytania 3
Następnie wyszukiwanie jest ograniczone do pojedynczego pola z możliwością wyszukiwania przy użyciu parametru searchFields
. Takie podejście jest doskonałym rozwiązaniem, aby zwiększyć wydajność zapytania, jeśli wiesz, że interesuje Cię tylko dopasowanie w niektórych polach.
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)}`);
}
Przykład zapytania 4
Inną typową opcją uwzględnienia w zapytaniu jest facets
. Aspekty umożliwiają zapewnienie samodzielnego przechodzenia do szczegółów z wyników w interfejsie użytkownika. Wyniki aspektów można przekształcić w pola wyboru w okienku wyników.
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)}`);
}
Przykład zapytania 5
Ostatnie zapytanie używa getDocument()
metody searchClient
. Dzięki temu można efektywnie pobierać dokument przy użyciu jego klucza.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Podsumowanie zapytań
Poprzednie zapytania pokazują wiele sposobów dopasowywania terminów w zapytaniu: wyszukiwanie pełnotekstowe, filtry i autouzupełnianie.
Wyszukiwanie pełnotekstowe i filtry są wykonywane przy użyciu searchClient.search
metody . Zapytanie wyszukiwania można przekazać w searchText
ciągu, podczas gdy wyrażenie filtru może zostać przekazane we filter
właściwości SearchOptions
klasy. Aby filtrować bez wyszukiwania, wystarczy przekazać wartość "*" dla searchText
parametru search
metody . Aby wyszukać bez filtrowania, pozostaw filter
właściwość niezastawioną lub nie przekazuj SearchOptions
w ogóle wystąpienia.
Uprzątnij zasoby
Podczas pracy w ramach własnej subskrypcji warto ukończyć projekt, określając, czy nadal potrzebujesz utworzonych zasobów. Zasoby, które pozostają uruchomione, mogą kosztować pieniądze. Zasoby można usunąć pojedynczo lub usunąć grupę zasobów, aby usunąć cały zestaw zasobów.
W witrynie Azure Portal możesz znaleźć zasoby i zarządzać nimi, wybierając pozycję Wszystkie zasoby lub Grupy zasobów w okienku po lewej stronie.
Jeśli używasz bezpłatnej usługi, pamiętaj, że masz ograniczenie do trzech indeksów, indeksatorów i źródeł danych. Aby utrzymać limit, możesz usunąć poszczególne elementy w witrynie Azure Portal.