Mulai cepat: Pencarian teks lengkap menggunakan Azure SDK
Pelajari cara menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian menggunakan data sampel untuk pencarian teks lengkap. Pencarian teks lengkap menggunakan Apache Lucene untuk pengindeksan dan kueri, dan algoritma peringkat BM25 untuk hasil penilaian.
Mulai cepat ini membuat dan mengkueri indeks mulai cepat hotel kecil yang berisi data tentang empat hotel.
Tip
Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Prasyarat
- Langganan Azure aktif - Buat langganan secara gratis
- Azure AI layanan Pencarian. Buat layanan jika Anda tidak memilikinya. Anda dapat menggunakan tingkat gratis untuk mulai cepat ini.
Prasyarat ID Microsoft Entra
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, Anda perlu:
- Instal Azure CLI yang digunakan untuk autentikasi tanpa kunci dengan ID Microsoft Entra.
- Tetapkan peran
Search Service Contributor
danSearch Index Data Contributor
ke akun pengguna Anda. Anda dapat menetapkan peran dalam portal Azure di bawah Kontrol akses (IAM)>Menambahkan penetapan peran. Untuk informasi selengkapnya, lihat Menyambungkan ke Pencarian Azure AI menggunakan peran.
Mengambil informasi sumber daya
Anda perlu mengambil informasi berikut untuk mengautentikasi aplikasi Anda dengan Layanan Pencarian Azure AI Anda:
Nama variabel | Nilai |
---|---|
SEARCH_API_ENDPOINT |
Nilai ini dapat ditemukan di portal Azure. Pilih layanan pencarian Anda lalu dari menu sebelah kiri, pilih Gambaran Umum. Nilai Url di bawah Essentials adalah titik akhir yang Anda butuhkan. Contoh titik akhir mungkin terlihat sepertihttps://mydemo.search.windows.net . |
Pelajari selengkapnya tentang autentikasi tanpa kunci dan mengatur variabel lingkungan.
Penyiapan
Buat folder
full-text-quickstart
baru untuk berisi aplikasi dan buka Visual Studio Code di folder tersebut dengan perintah berikut:mkdir full-text-quickstart && cd full-text-quickstart
Buat aplikasi konsol baru dengan perintah berikut:
dotnet new console
Instal pustaka klien Azure AI Search (Azure.Search.Documents) untuk .NET dengan:
dotnet add package Azure.Search.Documents
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, instal paket Azure.Identity dengan:
dotnet add package Azure.Identity
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, masuk ke Azure dengan perintah berikut:
az login
Membuat, memuat, dan mengkueri indeks pencarian
Di bagian pengaturan sebelumnya, Anda membuat aplikasi konsol baru dan menginstal pustaka klien Azure AI Search.
Di bagian ini, Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol. Untuk penjelasan terperinci tentang kode, lihat bagian menjelaskan kode .
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/");
DefaultAzureCredential credential = new();
Di Program.cs, tempelkan kode berikut.
serviceName
Edit variabel danapiKey
dengan nama layanan pencarian dan kunci API admin Anda.using System; using Azure; using Azure.Identity; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Models; namespace AzureSearch.Quickstart { class Program { static void Main(string[] args) { // Your search service endpoint Uri serviceEndpoint = new Uri($"https://<Put your search service NAME here>.search.windows.net/"); // Use the recommended keyless credential instead of the AzureKeyCredential credential. DefaultAzureCredential credential = new(); //AzureKeyCredential credential = new AzureKeyCredential("Your search service admin key"); // Create a SearchIndexClient to send create/delete index commands SearchIndexClient searchIndexClient = new SearchIndexClient(serviceEndpoint, credential); // Create a SearchClient to load and query documents string indexName = "hotels-quickstart"; SearchClient searchClient = new SearchClient(serviceEndpoint, indexName, credential); // Delete index if it exists Console.WriteLine("{0}", "Deleting index...\n"); DeleteIndexIfExists(indexName, searchIndexClient); // Create index Console.WriteLine("{0}", "Creating index...\n"); CreateIndex(indexName, searchIndexClient); SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName); // Load documents Console.WriteLine("{0}", "Uploading documents...\n"); UploadDocuments(ingesterClient); // Wait 2 secondsfor indexing to complete before starting queries (for demo and console-app purposes only) Console.WriteLine("Waiting for indexing...\n"); System.Threading.Thread.Sleep(2000); // Call the RunQueries method to invoke a series of queries Console.WriteLine("Starting queries...\n"); RunQueries(searchClient); // End the program Console.WriteLine("{0}", "Complete. Press any key to end this program...\n"); Console.ReadKey(); } // Delete the hotels-quickstart index to reuse its name private static void DeleteIndexIfExists(string indexName, SearchIndexClient searchIndexClient) { searchIndexClient.GetIndexNames(); { searchIndexClient.DeleteIndex(indexName); } } // Create hotels-quickstart index private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient) { FieldBuilder fieldBuilder = new FieldBuilder(); var searchFields = fieldBuilder.Build(typeof(Hotel)); var definition = new SearchIndex(indexName, searchFields); var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" }); definition.Suggesters.Add(suggester); searchIndexClient.CreateOrUpdateIndex(definition); } // Upload documents in a single Upload request. private static void UploadDocuments(SearchClient searchClient) { IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create( IndexDocumentsAction.Upload( new Hotel() { HotelId = "1", HotelName = "Secret Point Motel", Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.", Category = "Boutique", Tags = new[] { "pool", "air conditioning", "concierge" }, ParkingIncluded = false, LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero), Rating = 3.6, Address = new Address() { StreetAddress = "677 5th Ave", City = "New York", StateProvince = "NY", PostalCode = "10022", Country = "USA" } }), IndexDocumentsAction.Upload( new Hotel() { HotelId = "2", HotelName = "Twin Dome Motel", Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.", DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", Category = "Boutique", Tags = new[] { "pool", "free wifi", "concierge" }, ParkingIncluded = false, LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero), Rating = 3.60, Address = new Address() { StreetAddress = "140 University Town Center Dr", City = "Sarasota", StateProvince = "FL", PostalCode = "34243", Country = "USA" } }), IndexDocumentsAction.Upload( new Hotel() { HotelId = "3", HotelName = "Triple Landscape Hotel", Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.", DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", Category = "Resort and Spa", Tags = new[] { "air conditioning", "bar", "continental breakfast" }, ParkingIncluded = true, LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero), Rating = 4.80, Address = new Address() { StreetAddress = "3393 Peachtree Rd", City = "Atlanta", StateProvince = "GA", PostalCode = "30326", Country = "USA" } }), IndexDocumentsAction.Upload( new Hotel() { HotelId = "4", HotelName = "Sublime Cliff Hotel", Description = "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.", DescriptionFr = "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.", Category = "Boutique", Tags = new[] { "concierge", "view", "24-hour front desk service" }, ParkingIncluded = true, LastRenovationDate = new DateTimeOffset(1960, 2, 06, 0, 0, 0, TimeSpan.Zero), Rating = 4.60, Address = new Address() { StreetAddress = "7400 San Pedro Ave", City = "San Antonio", StateProvince = "TX", PostalCode = "78216", Country = "USA" } }) ); try { IndexDocumentsResult result = searchClient.IndexDocuments(batch); } catch (Exception) { // If for some reason any documents are dropped during indexing, you can compensate by delaying and // retrying. This simple demo just logs the failed document keys and continues. Console.WriteLine("Failed to index some of the documents: {0}"); } } // Run queries, use WriteDocuments to print output private static void RunQueries(SearchClient searchClient) { SearchOptions options; SearchResults<Hotel> response; // Query 1 Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n"); options = new SearchOptions() { IncludeTotalCount = true, Filter = "", OrderBy = { "" } }; options.Select.Add("HotelId"); options.Select.Add("HotelName"); options.Select.Add("Rating"); response = searchClient.Search<Hotel>("*", options); WriteDocuments(response); // Query 2 Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n"); options = new SearchOptions() { Filter = "Rating gt 4", OrderBy = { "Rating desc" } }; options.Select.Add("HotelId"); options.Select.Add("HotelName"); options.Select.Add("Rating"); response = searchClient.Search<Hotel>("hotels", options); WriteDocuments(response); // Query 3 Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n"); options = new SearchOptions() { SearchFields = { "Tags" } }; options.Select.Add("HotelId"); options.Select.Add("HotelName"); options.Select.Add("Tags"); response = searchClient.Search<Hotel>("pool", options); WriteDocuments(response); // Query 4 - Use Facets to return a faceted navigation structure for a given query // Filters are typically used with facets to narrow results on OnClick events Console.WriteLine("Query #4: Facet on 'Category'...\n"); options = new SearchOptions() { Filter = "" }; options.Facets.Add("Category"); options.Select.Add("HotelId"); options.Select.Add("HotelName"); options.Select.Add("Category"); response = searchClient.Search<Hotel>("*", options); WriteDocuments(response); // Query 5 Console.WriteLine("Query #5: Look up a specific document...\n"); Response<Hotel> lookupResponse; lookupResponse = searchClient.GetDocument<Hotel>("3"); Console.WriteLine(lookupResponse.Value.HotelId); // Query 6 Console.WriteLine("Query #6: Call Autocomplete on HotelName...\n"); var autoresponse = searchClient.Autocomplete("sa", "sg"); WriteDocuments(autoresponse); } // Write search results to console private static void WriteDocuments(SearchResults<Hotel> searchResults) { foreach (SearchResult<Hotel> result in searchResults.GetResults()) { Console.WriteLine(result.Document); } Console.WriteLine(); } private static void WriteDocuments(AutocompleteResults autoResults) { foreach (AutocompleteItem result in autoResults.Results) { Console.WriteLine(result.Text); } Console.WriteLine(); } } }
Di folder yang sama, buat file baru bernama Hotel.cs dan tempelkan kode berikut. Kode ini mendefinisikan struktur dokumen hotel.
using System; using System.Text.Json.Serialization; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; namespace AzureSearch.Quickstart { public partial class Hotel { [SimpleField(IsKey = true, IsFilterable = true)] public string HotelId { get; set; } [SearchableField(IsSortable = true)] public string HotelName { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)] public string Description { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)] [JsonPropertyName("Description_fr")] public string DescriptionFr { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string Category { get; set; } [SearchableField(IsFilterable = true, IsFacetable = true)] public string[] Tags { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public bool? ParkingIncluded { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public DateTimeOffset? LastRenovationDate { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public double? Rating { get; set; } [SearchableField] public Address Address { get; set; } } }
Buat file baru bernama Hotel.cs dan tempel kode berikut untuk menentukan struktur dokumen hotel. Atribut di bidang menentukan bagaimana atribut digunakan dalam aplikasi. Contoh
IsFilterable
atribut harus ditetapkan ke setiap bidang yang mendukung ekspresi filter.using System; using System.Text.Json.Serialization; using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; namespace AzureSearch.Quickstart { public partial class Hotel { [SimpleField(IsKey = true, IsFilterable = true)] public string HotelId { get; set; } [SearchableField(IsSortable = true)] public string HotelName { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)] public string Description { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrLucene)] [JsonPropertyName("Description_fr")] public string DescriptionFr { get; set; } [SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public string Category { get; set; } [SearchableField(IsFilterable = true, IsFacetable = true)] public string[] Tags { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public bool? ParkingIncluded { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public DateTimeOffset? LastRenovationDate { get; set; } [SimpleField(IsFilterable = true, IsSortable = true, IsFacetable = true)] public double? Rating { get; set; } [SearchableField] public Address Address { get; set; } } }
Buat file baru bernama Address.cs dan tempelkan kode berikut untuk menentukan struktur dokumen alamat.
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; } } }
Buat file baru bernama Hotel.Methods.cs dan tempel kode berikut untuk menentukan
ToString()
penimpaanHotel
untuk kelas .using System; using System.Text; namespace AzureSearch.Quickstart { public partial class Hotel { public override string ToString() { var builder = new StringBuilder(); if (!String.IsNullOrEmpty(HotelId)) { builder.AppendFormat("HotelId: {0}\n", HotelId); } if (!String.IsNullOrEmpty(HotelName)) { builder.AppendFormat("Name: {0}\n", HotelName); } if (!String.IsNullOrEmpty(Description)) { builder.AppendFormat("Description: {0}\n", Description); } if (!String.IsNullOrEmpty(DescriptionFr)) { builder.AppendFormat("Description (French): {0}\n", DescriptionFr); } if (!String.IsNullOrEmpty(Category)) { builder.AppendFormat("Category: {0}\n", Category); } if (Tags != null && Tags.Length > 0) { builder.AppendFormat("Tags: [ {0} ]\n", String.Join(", ", Tags)); } if (ParkingIncluded.HasValue) { builder.AppendFormat("Parking included: {0}\n", ParkingIncluded.Value ? "yes" : "no"); } if (LastRenovationDate.HasValue) { builder.AppendFormat("Last renovated on: {0}\n", LastRenovationDate); } if (Rating.HasValue) { builder.AppendFormat("Rating: {0}\n", Rating); } if (Address != null && !Address.IsEmpty) { builder.AppendFormat("Address: \n{0}\n", Address.ToString()); } return builder.ToString(); } } }
Buat file baru bernama Address.Methods.cs dan tempelkan kode berikut untuk menentukan
ToString()
penimpaanAddress
untuk kelas.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); } }
Bangun dan jalankan aplikasi dengan perintah berikut:
dotnet run
Output mencakup pesan dari Console.WriteLine, dengan penambahan informasi dan hasil permintaan.
Menjelaskan kode
Di bagian sebelumnya, Anda membuat aplikasi konsol baru dan menginstal pustaka klien Azure AI Search. Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol.
Di bagian ini, kami menjelaskan kode yang Anda tambahkan ke aplikasi konsol.
Buat klien pencarian
Di Program.cs, Anda membuat dua klien:
- SearchIndexClient membuat indeks.
- SearchClient memuat dan mengkueri indeks yang ada.
Kedua klien memerlukan titik akhir layanan pencarian dan kredensial yang dijelaskan sebelumnya di bagian informasi sumber daya.
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
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 . . .
}
Buat indeks
Mulai cepat ini membangun indeks Hotel yang Anda muat dengan data hotel dan menjalankan kueri. Dalam langkah ini, Anda menentukan bidang dalam indeks. Setiap definisi bidang menyertakan nama, tipe data, dan atribut yang menentukan cara bidang digunakan.
Dalam contoh ini, metode sinkron pustaka Azure.Search.Documents digunakan untuk kesederhanaan dan keterbacaan. Namun, untuk skenario produksi, Anda harus menggunakan metode asinkron agar aplikasi Anda tetap skalabel dan responsif. Misalnya, Anda akan menggunakan CreateIndexAsync daripada CreateIndex.
Menentukan struktur
Anda membuat dua kelas pembantu, Hotel.cs dan Address.cs, untuk menentukan struktur dokumen hotel dan alamatnya. Kelas ini Hotel
mencakup bidang untuk ID hotel, nama, deskripsi, kategori, tag, parkir, tanggal renovasi, peringkat, dan alamat. Kelas ini Address
mencakup bidang untuk alamat jalan, kota, negara bagian/provinsi, kode pos, dan negara/wilayah.
Di pustaka klien Azure.Search.Documents, Anda dapat menggunakan SearchableField dan SimpleField untuk menyederhanakan definisi bidang. Keduanya merupakan turunan dari SearchField dan berpotensi menyederhanakan kode Anda:
SimpleField
dapat berupa jenis data apa pun, selalu tidak dapat dicari (diabaikan untuk kueri pencarian teks lengkap), dan dapat diambil (tidak tersembunyi). Atribut lain tidak aktif secara default, tetapi dapat diaktifkan. Anda mungkin menggunakanSimpleField
untuk ID dokumen atau bidang yang hanya digunakan dalam filter, faset, atau profil penilaian. Jika demikian, pastikan untuk menerapkan atribut apa pun yang diperlukan untuk skenario, sepertiIsKey = true
untuk ID dokumen. Untuk informasi lebih lanjut, lihat SimpleFieldAttribute.cs dalam kode sumber.SearchableField
harus berupa string, dan selalu dapat dicari dan diambil. Atribut lain tidak aktif secara default, tetapi dapat diaktifkan. Karena jenis bidang ini dapat dicari, ia mendukung sinonim dan kelengkapan lengkap properti penganalisis. atau informasi lebih lanjut, lihat SearchableFieldAttribute.csdalam kode sumber.
Apakah Anda menggunakan dasar SearchField
API atau salah satu model pembantu, Anda harus secara eksplisit mengaktifkan atribut filter, faset, dan sort. Misalnya, IsFilterable, IsSortable, dan IsFacetable harus dikaitkan secara eksplisit, seperti yang ditunjukkan pada sampel sebelumnya.
Membuat indeks pencarian
Di Program.cs, Anda membuat objek SearchIndex , lalu memanggil metode CreateIndex untuk mengekspresikan indeks di layanan pencarian Anda. Indeks juga termasuk SearchSuggester untuk mengaktifkan pelengkapan otomatis pada bidang yang ditentukan.
// 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);
}
Muat dokumen
Pencarian Azure AI mencari konten yang disimpan dalam layanan. Dalam langkah ini, Anda memuat dokumen JSON yang sesuai dengan indeks hotel yang Anda buat.
Di Pencarian Azure AI, dokumen pencarian adalah struktur data yang merupakan input ke pengindeksan dan output dari kueri. Seperti yang diperoleh dari sumber data eksternal, input dokumen mungkin berupa baris dalam database, blob dalam penyimpanan Blob, atau dokumen JSON pada disk. Dalam contoh ini, pintasan diambil dan dokumen JSON disematkan untuk empat hotel dalam kode itu sendiri.
Saat mengunggah dokumen, Anda harus menggunakan obyek IndexDocumentsBatch. Objek IndexDocumentsBatch
berisi kumpulan Tindakan, yang masing-masing berisi dokumen dan properti yang memberi tahu Azure AI Cari tindakan apa yang harus dilakukan (unggah, gabungkan, hapus, dan gabungkanOrUpload).
Dalam Program.cs, Anda membuat array dokumen dan tindakan indeks, lalu meneruskan array ke IndexDocumentsBatch
. Dokumen berikut sesuai dengan indeks hotel-quickstart, seperti yang didefinisikan oleh kelas hotel.
// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "1",
HotelName = "Stay-Kay City Hotel",
Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.",
Category = "Boutique",
Tags = new[] { "pool", "air conditioning", "concierge" },
ParkingIncluded = false,
LastRenovationDate = new DateTimeOffset(1970, 1, 18, 0, 0, 0, TimeSpan.Zero),
Rating = 3.6,
Address = new Address()
{
StreetAddress = "677 5th Ave",
City = "New York",
StateProvince = "NY",
PostalCode = "10022",
Country = "USA"
}
}),
// REDACTED FOR BREVITY
}
Setelah Anda menginisialisasi IndexDocumentsBatch objek, Anda dapat mengirimkannya ke indeks dengan memanggil IndexDocuments pada obyek SearchClient Anda.
Anda memuat dokumen menggunakan SearchClient di Main()
, tetapi operasi ini juga memerlukan hak admin pada layanan, yang biasanya terkait dengan SearchIndexClient. Salah satu cara untuk menyiapkan operasi ini adalah dengan mendapatkan SearchClient melalui SearchIndexClient
(searchIndexClient
dalam contoh ini).
SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);
// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);
Karena kami memiliki aplikasi konsol yang menjalankan semua perintah secara berurutan, kami menambahkan waktu tunggu 2 detik antara pengindeksan dan kueri.
// 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);
Penundaan 2 detik mengkompensasi pengindeksan, yang tidak sinkron, sehingga semua dokumen dapat diindeks sebelum kueri dieksekusi. Pengodean dalam penundaan biasanya hanya diperlukan dalam demo, pengujian, dan aplikasi contoh.
Mencari indeks
Anda bisa mendapatkan hasil kueri segera setelah dokumen pertama diindeks, tetapi pengujian aktual indeks Anda harus menunggu hingga semua dokumen diindeks.
Bagian ini menambahkan dua bagian fungsionalitas: logika kueri, dan hasil. Untuk pertanyaan, gunakan metode Cari. Metode ini mengambil teks pencarian (string kueri) dan opsi lainnya.
SearchResults Metode ini mengambil teks pencarian (string kueri) serta lainnya.
Dalam Program.cs, WriteDocuments
metode mencetak hasil pencarian ke konsol.
// 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();
}
Contoh kueri 1
Metode ini RunQueries
menjalankan kueri dan mengembalikan hasil. Hasilnya merupakan objek Hotel. Sampel ini menunjukkan metode tanda tangan dan permintaan pertama. Kueri ini menunjukkan Select
parameter yang memungkinkan Anda menyusun hasil menggunakan bidang yang dipilih dari dokumen.
// 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
}
Contoh kueri 2
Di kueri kedua, cari pada istilah, tambahkan filter yang memilih dokumen di mana Peringkat lebih besar dari 4, lalu urutkan menurut Peringkat dalam urutan menurut. Filter merupakan ekspresi boolean yang dievaluasi atas bidang IsFilterable dalam indeks. Filter permintaan baik itu menyertakan atau mengecualikan nilai. Dengan demikian, tidak ada skor relevansi yang terkait dengan kueri filter.
// 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);
Contoh kueri 3
Kueri ketiga menunjukkan searchFields
, digunakan untuk mencakup operasi pencarian teks lengkap ke bidang tertentu.
// 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);
Contoh kueri 4
Kueri keempat menunjukkan facets
, yang dapat digunakan untuk menyusun struktur navigasi tersaring.
// 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);
Contoh kueri 5
Di permintaan kelima, kembalikan sebuah dokumen tertentu. Pencarian dokumen adalah respons umum terhadap OnClick
peristiwa dalam kumpulan hasil.
// 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);
Contoh kueri 6
Kueri terakhir memperlihatkan sintaks untuk pelengkapan otomatis, mensimulasikan input pengguna parsial sa yang menyelesaikan dua kemungkinan kecocokan di sourceFields yang terkait dengan pemberi saran yang Anda tentukan dalam indeks.
// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName that starts with 'sa'...\n");
var autoresponse = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);
Ringkasan kueri
Permintaan sebelumnya memperlihatkan beberapa cara pencocokan istilah dalam permintaan:pencarian teks lengkap, filter, dan kelengkapan otomatis.
Pencarian dan filter teks lengkap dilakukan menggunakan metode SearchClient.Search. Sebuah permintaan penelusuran dapat diteruskan dalam searchText
string, sementara ekspresi filter dapat diteruskan dalam Filter properti dari kelas SearchOptions. Untuk memfilter tanpa mencari, "*"
cukup searchText
lewati parameter metode Pencarian. Untuk mencari tanpa pemfilteran, biarkan Filter
properti tidak diatur, atau tidak meneruskan SearchOptions
instans sama sekali.
Pelajari cara menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian menggunakan data sampel untuk pencarian teks lengkap. Pencarian teks lengkap menggunakan Apache Lucene untuk pengindeksan dan kueri, dan algoritma peringkat BM25 untuk hasil penilaian.
Mulai cepat ini membuat dan mengkueri indeks mulai cepat hotel kecil yang berisi data tentang empat hotel.
Tip
Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Prasyarat
- Langganan Azure aktif - Buat langganan secara gratis
- Azure AI layanan Pencarian. Buat layanan jika Anda tidak memilikinya. Anda dapat menggunakan tingkat gratis untuk mulai cepat ini.
Prasyarat ID Microsoft Entra
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, Anda perlu:
- Instal Azure CLI yang digunakan untuk autentikasi tanpa kunci dengan ID Microsoft Entra.
- Tetapkan peran
Search Service Contributor
danSearch Index Data Contributor
ke akun pengguna Anda. Anda dapat menetapkan peran dalam portal Azure di bawah Kontrol akses (IAM)>Menambahkan penetapan peran. Untuk informasi selengkapnya, lihat Menyambungkan ke Pencarian Azure AI menggunakan peran.
Mengambil informasi sumber daya
Anda perlu mengambil informasi berikut untuk mengautentikasi aplikasi Anda dengan Layanan Pencarian Azure AI Anda:
Nama variabel | Nilai |
---|---|
SEARCH_API_ENDPOINT |
Nilai ini dapat ditemukan di portal Azure. Pilih layanan pencarian Anda lalu dari menu sebelah kiri, pilih Gambaran Umum. Nilai Url di bawah Essentials adalah titik akhir yang Anda butuhkan. Contoh titik akhir mungkin terlihat sepertihttps://mydemo.search.windows.net . |
Pelajari selengkapnya tentang autentikasi tanpa kunci dan mengatur variabel lingkungan.
Penyiapan
Contoh dalam mulai cepat ini berfungsi dengan Runtime Java. Pasang Java Development Kit seperti Azul Zulu OpenJDK. Microsoft Build of OpenJDK atau JDK pilihan Anda juga harus berfungsi.
Menginstal Apache Maven. Kemudian jalankan
mvn -v
untuk mengonfirmasi keberhasilan penginstalan.Buat file baru
pom.xml
di akar proyek Anda, dan salin kode berikut ke dalamnya:<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>
Instal dependensi termasuk pustaka klien Azure AI Search (Azure.Search.Documents) untuk pustaka klien Java dan Azure Identity untuk Java dengan:
mvn clean dependency:copy-dependencies
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, masuk ke Azure dengan perintah berikut:
az login
Membuat, memuat, dan mengkueri indeks pencarian
Di bagian penyetelan sebelumnya, Anda menginstal pustaka klien Azure AI Search dan dependensi lainnya.
Di bagian ini, Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol. Untuk penjelasan terperinci tentang kode, lihat bagian menjelaskan kode .
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Buat file baru bernama App.java dan tempelkan kode berikut ke App.java:
import java.util.Arrays; import java.util.ArrayList; import java.time.OffsetDateTime; import java.time.ZoneOffset; import java.time.LocalDateTime; import java.time.LocalDate; import java.time.LocalTime; import com.azure.core.util.Configuration; import com.azure.core.util.Context; import com.azure.identity.DefaultAzureCredential; import com.azure.identity.DefaultAzureCredentialBuilder; import com.azure.search.documents.SearchClient; import com.azure.search.documents.SearchClientBuilder; import com.azure.search.documents.indexes.SearchIndexClient; import com.azure.search.documents.indexes.SearchIndexClientBuilder; import com.azure.search.documents.indexes.models.IndexDocumentsBatch; import com.azure.search.documents.models.SearchOptions; import com.azure.search.documents.indexes.models.SearchIndex; import com.azure.search.documents.indexes.models.SearchSuggester; import com.azure.search.documents.util.AutocompletePagedIterable; import com.azure.search.documents.util.SearchPagedIterable; public class App { public static void main(String[] args) { // Your search service endpoint "https://<Put your search service NAME here>.search.windows.net/"; // Use the recommended keyless credential instead of the AzureKeyCredential credential. DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build(); //AzureKeyCredential credential = new AzureKeyCredential("<Your search service admin key>"); // Create a SearchIndexClient to send create/delete index commands SearchIndexClient searchIndexClient = new SearchIndexClientBuilder() .endpoint(searchServiceEndpoint) .credential(credential) .buildClient(); // Create a SearchClient to load and query documents String indexName = "hotels-quickstart-java"; SearchClient searchClient = new SearchClientBuilder() .endpoint(searchServiceEndpoint) .credential(credential) .indexName(indexName) .buildClient(); // Create Search Index for Hotel model searchIndexClient.createOrUpdateIndex( new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null)) .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName")))); // Upload sample hotel documents to the Search Index uploadDocuments(searchClient); // Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only) System.out.println("Waiting for indexing...\n"); try { Thread.sleep(2000); } catch (InterruptedException e) { } // Call the RunQueries method to invoke a series of queries System.out.println("Starting queries...\n"); RunQueries(searchClient); // End the program System.out.println("Complete.\n"); } // Upload documents in a single Upload request. private static void uploadDocuments(SearchClient searchClient) { var hotelList = new ArrayList<Hotel>(); var hotel = new Hotel(); hotel.hotelId = "1"; hotel.hotelName = "Stay-Kay City Hotel"; hotel.description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities."; hotel.descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique."; hotel.category = "Boutique"; hotel.tags = new String[] { "pool", "air conditioning", "concierge" }; hotel.parkingIncluded = false; hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1970, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC); hotel.rating = 3.6; hotel.address = new Address(); hotel.address.streetAddress = "677 5th Ave"; hotel.address.city = "New York"; hotel.address.stateProvince = "NY"; hotel.address.postalCode = "10022"; hotel.address.country = "USA"; hotelList.add(hotel); hotel = new Hotel(); hotel.hotelId = "2"; hotel.hotelName = "Old Century Hotel"; hotel.description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts."; hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne."; hotel.category = "Boutique"; hotel.tags = new String[] { "pool", "free wifi", "concierge" }; hotel.parkingIncluded = false; hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1979, 2, 18), LocalTime.of(0, 0)), ZoneOffset.UTC); hotel.rating = 3.60; hotel.address = new Address(); hotel.address.streetAddress = "140 University Town Center Dr"; hotel.address.city = "Sarasota"; hotel.address.stateProvince = "FL"; hotel.address.postalCode = "34243"; hotel.address.country = "USA"; hotelList.add(hotel); hotel = new Hotel(); hotel.hotelId = "3"; hotel.hotelName = "Gastronomic Landscape Hotel"; hotel.description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services."; hotel.descriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne."; hotel.category = "Resort and Spa"; hotel.tags = new String[] { "air conditioning", "bar", "continental breakfast" }; hotel.parkingIncluded = true; hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2015, 9, 20), LocalTime.of(0, 0)), ZoneOffset.UTC); hotel.rating = 4.80; hotel.address = new Address(); hotel.address.streetAddress = "3393 Peachtree Rd"; hotel.address.city = "Atlanta"; hotel.address.stateProvince = "GA"; hotel.address.postalCode = "30326"; hotel.address.country = "USA"; hotelList.add(hotel); hotel = new Hotel(); hotel.hotelId = "4"; hotel.hotelName = "Sublime Palace Hotel"; hotel.description = "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace."; hotel.descriptionFr = "Le Sublime Palace Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Palace fait partie d'un Palace 1800 restauré avec amour."; hotel.category = "Boutique"; hotel.tags = new String[] { "concierge", "view", "24-hour front desk service" }; hotel.parkingIncluded = true; hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1960, 2, 06), LocalTime.of(0, 0)), ZoneOffset.UTC); hotel.rating = 4.60; hotel.address = new Address(); hotel.address.streetAddress = "7400 San Pedro Ave"; hotel.address.city = "San Antonio"; hotel.address.stateProvince = "TX"; hotel.address.postalCode = "78216"; hotel.address.country = "USA"; hotelList.add(hotel); var batch = new IndexDocumentsBatch<Hotel>(); batch.addMergeOrUploadActions(hotelList); try { searchClient.indexDocuments(batch); } catch (Exception e) { e.printStackTrace(); // If for some reason any documents are dropped during indexing, you can compensate by delaying and // retrying. This simple demo just logs failure and continues System.err.println("Failed to index some of the documents"); } } // Write search results to console private static void WriteSearchResults(SearchPagedIterable searchResults) { searchResults.iterator().forEachRemaining(result -> { Hotel hotel = result.getDocument(Hotel.class); System.out.println(hotel); }); System.out.println(); } // Write autocomplete results to console private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults) { autocompleteResults.iterator().forEachRemaining(result -> { String text = result.getText(); System.out.println(text); }); System.out.println(); } // Run queries, use WriteDocuments to print output private static void RunQueries(SearchClient searchClient) { // Query 1 System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n"); SearchOptions options = new SearchOptions(); options.setIncludeTotalCount(true); options.setFilter(""); options.setOrderBy(""); options.setSelect("HotelId", "HotelName", "Address/City"); WriteSearchResults(searchClient.search("*", options, Context.NONE)); // Query 2 System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n"); options = new SearchOptions(); options.setFilter("Rating gt 4"); options.setOrderBy("Rating desc"); options.setSelect("HotelId", "HotelName", "Rating"); WriteSearchResults(searchClient.search("hotels", options, Context.NONE)); // Query 3 System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n"); options = new SearchOptions(); options.setSearchFields("Tags"); options.setSelect("HotelId", "HotelName", "Tags"); WriteSearchResults(searchClient.search("pool", options, Context.NONE)); // Query 4 System.out.println("Query #4: Facet on 'Category'...\n"); options = new SearchOptions(); options.setFilter(""); options.setFacets("Category"); options.setSelect("HotelId", "HotelName", "Category"); WriteSearchResults(searchClient.search("*", options, Context.NONE)); // Query 5 System.out.println("Query #5: Look up a specific document...\n"); Hotel lookupResponse = searchClient.getDocument("3", Hotel.class); System.out.println(lookupResponse.hotelId); System.out.println(); // Query 6 System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n"); WriteAutocompleteResults(searchClient.autocomplete("s", "sg")); } }
Buat file baru bernama Hotel.java dan tempelkan kode berikut ke dalam Hotel.java:
import com.azure.search.documents.indexes.SearchableField; import com.azure.search.documents.indexes.SimpleField; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.annotation.JsonInclude.Include; import java.time.OffsetDateTime; /** * Model class representing a hotel. */ @JsonInclude(Include.NON_NULL) public class Hotel { /** * Hotel ID */ @JsonProperty("HotelId") @SimpleField(isKey = true) public String hotelId; /** * Hotel name */ @JsonProperty("HotelName") @SearchableField(isSortable = true) public String hotelName; /** * Description */ @JsonProperty("Description") @SearchableField(analyzerName = "en.microsoft") public String description; /** * French description */ @JsonProperty("DescriptionFr") @SearchableField(analyzerName = "fr.lucene") public String descriptionFr; /** * Category */ @JsonProperty("Category") @SearchableField(isFilterable = true, isSortable = true, isFacetable = true) public String category; /** * Tags */ @JsonProperty("Tags") @SearchableField(isFilterable = true, isFacetable = true) public String[] tags; /** * Whether parking is included */ @JsonProperty("ParkingIncluded") @SimpleField(isFilterable = true, isSortable = true, isFacetable = true) public Boolean parkingIncluded; /** * Last renovation time */ @JsonProperty("LastRenovationDate") @SimpleField(isFilterable = true, isSortable = true, isFacetable = true) public OffsetDateTime lastRenovationDate; /** * Rating */ @JsonProperty("Rating") @SimpleField(isFilterable = true, isSortable = true, isFacetable = true) public Double rating; /** * Address */ @JsonProperty("Address") public Address address; @Override public String toString() { try { return new ObjectMapper().writeValueAsString(this); } catch (JsonProcessingException e) { e.printStackTrace(); return ""; } } }
Buat file baru bernama Address.java dan tempelkan kode berikut ke dalam 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; }
Jalankan aplikasi konsol baru Anda:
javac Address.java App.java Hotel.java -cp ".;target\dependency\*" java -cp ".;target\dependency\*" App
Menjelaskan kode
Di bagian sebelumnya, Anda membuat aplikasi konsol baru dan menginstal pustaka klien Azure AI Search. Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol.
Di bagian ini, kami menjelaskan kode yang Anda tambahkan ke aplikasi konsol.
Buat klien pencarian
Dalam App.java Anda membuat dua klien:
- SearchIndexClient membuat indeks.
- SearchClient memuat dan mengkueri indeks yang ada.
Kedua klien memerlukan titik akhir layanan pencarian dan kredensial yang dijelaskan sebelumnya di bagian informasi sumber daya.
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
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 . . .
}
Buat indeks
Mulai cepat ini membangun indeks Hotel yang Anda muat dengan data hotel dan menjalankan kueri. Dalam langkah ini, Anda menentukan bidang dalam indeks. Setiap definisi bidang menyertakan nama, tipe data, dan atribut yang menentukan cara bidang digunakan.
Dalam contoh ini, metode sinkron pustaka Azure.Search.Documents digunakan untuk kesederhanaan dan keterbacaan. Namun, untuk skenario produksi, Anda harus menggunakan metode asinkron agar aplikasi Anda tetap skalabel dan responsif. Misalnya, Anda akan menggunakan CreateIndexAsync daripada CreateIndex.
Menentukan struktur
Anda membuat dua kelas pembantu, Hotel.java dan Address.java, untuk menentukan struktur dokumen hotel dan alamatnya. Kelas Hotel mencakup bidang untuk ID hotel, nama, deskripsi, kategori, tag, parkir, tanggal renovasi, peringkat, dan alamat. Kelas Alamat mencakup bidang untuk alamat jalan, kota, negara bagian/provinsi, kode pos, dan negara/wilayah.
Di Pustaka klien Azure.Search.Documents, Anda dapat menggunakan SearchableField dan SimpleField untuk merampingkan definisi bidang.
-
SimpleField
dapat berupa jenis data apa pun, selalu tidak dapat dicari (diabaikan untuk kueri pencarian teks lengkap), dan dapat diambil (tidak tersembunyi). Atribut lain tidak aktif secara default, tetapi dapat diaktifkan. Anda mungkin menggunakan SimpleField untuk ID dokumen atau bidang yang hanya digunakan dalam filter, faset, atau profil penilaian. Jika demikian, pastikan untuk menerapkan atribut apa pun yang diperlukan untuk skenario, seperti IsKey = true untuk ID dokumen. -
SearchableField
harus berupa string, dan selalu dapat dicari dan diambil. Atribut lain tidak aktif secara default, tetapi dapat diaktifkan. Karena jenis bidang ini dapat dicari, ia mendukung sinonim dan kelengkapan lengkap properti penganalisis.
Apakah Anda menggunakan dasar SearchField
API atau salah satu model pembantu, Anda harus secara eksplisit mengaktifkan atribut filter, faset, dan sort. Misalnya, isFilterable
, isSortable
, dan isFacetable
harus diatribusikan secara eksplisit, seperti yang ditunjukkan pada sampel sebelumnya.
Membuat indeks pencarian
Di App.java
, Anda membuat SearchIndex
objek dalam main
metode , lalu memanggil createOrUpdateIndex
metode untuk membuat indeks di layanan pencarian Anda. Indeks juga menyertakan SearchSuggester
untuk mengaktifkan pelengkapan otomatis pada bidang yang ditentukan.
// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
.setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));
Muat dokumen
Pencarian Azure AI mencari konten yang disimpan dalam layanan. Dalam langkah ini, Anda memuat dokumen JSON yang sesuai dengan indeks hotel yang Anda buat.
Di Pencarian Azure AI, dokumen pencarian adalah struktur data yang merupakan input ke pengindeksan dan output dari kueri. Seperti yang diperoleh dari sumber data eksternal, input dokumen mungkin berupa baris dalam database, blob dalam penyimpanan Blob, atau dokumen JSON pada disk. Dalam contoh ini, pintasan diambil dan dokumen JSON disematkan untuk empat hotel dalam kode itu sendiri.
Saat mengunggah dokumen, Anda harus menggunakan obyek IndexDocumentsBatch. Objek IndexDocumentsBatch
berisi kumpulan IndexActions, yang masing-masing berisi dokumen dan properti yang memberi tahu Azure AI Cari tindakan apa yang harus dilakukan (unggah, gabungkan, hapus, dan gabungkanOrUpload).
Di App.java
, Anda membuat dokumen dan tindakan indeks, lalu meneruskannya ke IndexDocumentsBatch
. Dokumen berikut sesuai dengan indeks hotel-quickstart, seperti yang didefinisikan oleh kelas hotel.
private static void uploadDocuments(SearchClient searchClient)
{
var hotelList = new ArrayList<Hotel>();
var hotel = new Hotel();
hotel.hotelId = "1";
hotel.hotelName = "Stay-Kay City Hotel";
hotel.description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.";
hotel.descriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.";
hotel.category = "Boutique";
hotel.tags = new String[] { "pool", "air conditioning", "concierge" };
hotel.parkingIncluded = false;
hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(1970, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
hotel.rating = 3.6;
hotel.address = new Address();
hotel.address.streetAddress = "677 5th Ave";
hotel.address.city = "New York";
hotel.address.stateProvince = "NY";
hotel.address.postalCode = "10022";
hotel.address.country = "USA";
hotelList.add(hotel);
// REDACTED FOR BREVITY
var batch = new IndexDocumentsBatch<Hotel>();
batch.addMergeOrUploadActions(hotelList);
try
{
searchClient.indexDocuments(batch);
}
catch (Exception e)
{
e.printStackTrace();
// If for some reason any documents are dropped during indexing, you can compensate by delaying and
// retrying. This simple demo just logs failure and continues
System.err.println("Failed to index some of the documents");
}
}
Setelah menginisialisasi IndexDocumentsBatch
objek, Anda dapat mengirimkannya ke indeks dengan memanggil indexDocuments pada objek Anda SearchClient
.
Anda memuat dokumen menggunakan SearchClient di main()
, tetapi operasi ini juga memerlukan hak admin pada layanan, yang biasanya terkait dengan SearchIndexClient. Salah satu cara untuk menyiapkan operasi ini adalah dengan mendapatkan SearchClient melalui SearchIndexClient
(searchIndexClient
dalam contoh ini).
uploadDocuments(searchClient);
Karena kami memiliki aplikasi konsol yang menjalankan semua perintah secara berurutan, kami menambahkan waktu tunggu 2 detik antara pengindeksan dan kueri.
// 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)
{
}
Penundaan 2 detik mengkompensasi pengindeksan, yang tidak sinkron, sehingga semua dokumen dapat diindeks sebelum kueri dieksekusi. Pengodean dalam penundaan biasanya hanya diperlukan dalam demo, pengujian, dan aplikasi contoh.
Mencari indeks
Anda bisa mendapatkan hasil kueri segera setelah dokumen pertama diindeks, tetapi pengujian aktual indeks Anda harus menunggu hingga semua dokumen diindeks.
Bagian ini menambahkan dua bagian fungsionalitas: logika dan hasil kueri. Untuk pertanyaan, gunakan metode Cari. Metode ini mengambil teks pencarian (string kueri) dan opsi lainnya.
Dalam App.java
, WriteDocuments
metode mencetak hasil pencarian ke konsol.
// 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();
}
Contoh kueri 1
Metode ini RunQueries
menjalankan kueri dan mengembalikan hasil. Hasilnya merupakan objek Hotel. Sampel ini menunjukkan metode tanda tangan dan permintaan pertama. Kueri ini menunjukkan Select
parameter yang memungkinkan Anda menyusun hasil menggunakan bidang yang dipilih dari dokumen.
// 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));
}
Contoh kueri 2
Di kueri kedua, cari pada istilah, tambahkan filter yang memilih dokumen di mana Peringkat lebih besar dari 4, lalu urutkan menurut Peringkat dalam urutan menurut. Filter adalah ekspresi boolean yang dievaluasi atas isFilterable
bidang dalam indeks. Filter permintaan baik itu menyertakan atau mengecualikan nilai. Dengan demikian, tidak ada skor relevansi yang terkait dengan kueri filter.
// 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));
Contoh kueri 3
Kueri ketiga menunjukkan searchFields
, digunakan untuk mencakup operasi pencarian teks lengkap ke bidang tertentu.
// 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));
Contoh kueri 4
Kueri keempat menunjukkan facets
, yang dapat digunakan untuk menyusun struktur navigasi tersaring.
// 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));
Contoh kueri 5
Di permintaan kelima, kembalikan sebuah dokumen tertentu.
// 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();
Contoh kueri 6
Kueri terakhir memperlihatkan sintaks untuk pelengkapan otomatis, mensimulasikan input pengguna parsial s yang menyelesaikan dua kemungkinan kecocokan dalam sourceFields
yang terkait dengan pemberi saran yang Anda tentukan dalam indeks.
// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");
WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));
Ringkasan kueri
Permintaan sebelumnya memperlihatkan beberapa cara pencocokan istilah dalam permintaan:pencarian teks lengkap, filter, dan kelengkapan otomatis.
Pencarian teks lengkap dan filter dilakukan menggunakan metode SearchClient.search . Kueri pencarian dapat diteruskan dalam searchText
string, sementara ekspresi filter dapat diteruskan di filter
properti kelas SearchOptions . Untuk memfilter tanpa mencari, cukup teruskan "*" untuk searchText
parameter search
metode . Untuk mencari tanpa pemfilteran, biarkan filter
properti tidak diatur, atau tidak meneruskan SearchOptions
instans sama sekali.
Pelajari cara menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian menggunakan data sampel untuk pencarian teks lengkap. Pencarian teks lengkap menggunakan Apache Lucene untuk pengindeksan dan kueri, dan algoritma peringkat BM25 untuk hasil penilaian.
Mulai cepat ini membuat dan mengkueri indeks mulai cepat hotel kecil yang berisi data tentang empat hotel.
Tip
Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Prasyarat
- Langganan Azure aktif - Buat langganan secara gratis
- Azure AI layanan Pencarian. Buat layanan jika Anda tidak memilikinya. Anda dapat menggunakan tingkat gratis untuk mulai cepat ini.
Prasyarat ID Microsoft Entra
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, Anda perlu:
- Instal Azure CLI yang digunakan untuk autentikasi tanpa kunci dengan ID Microsoft Entra.
- Tetapkan peran
Search Service Contributor
danSearch Index Data Contributor
ke akun pengguna Anda. Anda dapat menetapkan peran dalam portal Azure di bawah Kontrol akses (IAM)>Menambahkan penetapan peran. Untuk informasi selengkapnya, lihat Menyambungkan ke Pencarian Azure AI menggunakan peran.
Mengambil informasi sumber daya
Anda perlu mengambil informasi berikut untuk mengautentikasi aplikasi Anda dengan Layanan Pencarian Azure AI Anda:
Nama variabel | Nilai |
---|---|
SEARCH_API_ENDPOINT |
Nilai ini dapat ditemukan di portal Azure. Pilih layanan pencarian Anda lalu dari menu sebelah kiri, pilih Gambaran Umum. Nilai Url di bawah Essentials adalah titik akhir yang Anda butuhkan. Contoh titik akhir mungkin terlihat sepertihttps://mydemo.search.windows.net . |
Pelajari selengkapnya tentang autentikasi tanpa kunci dan mengatur variabel lingkungan.
Penyiapan
Buat folder
full-text-quickstart
baru untuk berisi aplikasi dan buka Visual Studio Code di folder tersebut dengan perintah berikut:mkdir full-text-quickstart && cd full-text-quickstart
package.json
Buat dengan perintah berikut:npm init -y
Instal pustaka klien Azure AI Search (Azure.Search.Documents) untuk JavaScript dengan:
npm install @azure/search-documents
Untuk autentikasi tanpa kata sandi yang direkomendasikan , instal pustaka klien Azure Identity dengan:
npm install @azure/identity
Membuat, memuat, dan mengkueri indeks pencarian
Di bagian penyetelan sebelumnya, Anda menginstal pustaka klien Azure AI Search dan dependensi lainnya.
Di bagian ini, Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol. Untuk penjelasan terperinci tentang kode, lihat bagian menjelaskan kode .
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
String searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
DefaultAzureCredential credential = new DefaultAzureCredentialBuilder().build();
Buat file baru bernama index.js dan tempelkan kode berikut ke index.js:
// Import from the @azure/search-documents library import { SearchIndexClient, odata } from "@azure/search-documents"; // Import from the Azure Identity library import { DefaultAzureCredential } from "@azure/identity"; // Importing the hotels sample data import hotelData from './hotels.json' assert { type: "json" }; // Load the .env file if it exists import * as dotenv from "dotenv"; dotenv.config(); // Defining the index definition const indexDefinition = { "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "Description_fr", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "fr.lucene" }, { "name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true }, { "name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true }, { "name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true }, { "name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true }, { "name": "Address", "type": "Edm.ComplexType", "fields": [ { "name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true }, { "name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true } ] } ], "suggesters": [ { "name": "sg", "searchMode": "analyzingInfixMatching", "sourceFields": [ "HotelName" ] } ] }; async function main() { // Your search service endpoint const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/"; // Use the recommended keyless credential instead of the AzureKeyCredential credential. const credential = new DefaultAzureCredential(); //const credential = new AzureKeyCredential(Your search service admin key); // Create a SearchIndexClient to send create/delete index commands const searchIndexClient = new SearchIndexClient(searchServiceEndpoint, credential); // Creating a search client to upload documents and issue queries const indexName = "hotels-quickstart"; const searchClient = searchIndexClient.getSearchClient(indexName); console.log('Checking if index exists...'); await deleteIndexIfExists(searchIndexClient, indexName); console.log('Creating index...'); let index = await searchIndexClient.createIndex(indexDefinition); console.log(`Index named ${index.name} has been created.`); console.log('Uploading documents...'); let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']); console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `); // waiting one second for indexing to complete (for demo purposes only) sleep(1000); console.log('Querying the index...'); console.log(); await sendQueries(searchClient); } async function deleteIndexIfExists(searchIndexClient, indexName) { try { await searchIndexClient.deleteIndex(indexName); console.log('Deleting index...'); } catch { console.log('Index does not exist yet.'); } } async function sendQueries(searchClient) { // Query 1 console.log('Query #1 - search everything:'); let searchOptions = { includeTotalCount: true, select: ["HotelId", "HotelName", "Rating"] }; let searchResults = await searchClient.search("*", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(`Result count: ${searchResults.count}`); console.log(); // Query 2 console.log('Query #2 - search with filter, orderBy, and select:'); let state = 'FL'; searchOptions = { filter: odata `Address/StateProvince eq ${state}`, orderBy: ["Rating desc"], select: ["HotelId", "HotelName", "Rating"] }; searchResults = await searchClient.search("wifi", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 3 console.log('Query #3 - limit searchFields:'); searchOptions = { select: ["HotelId", "HotelName", "Rating"], searchFields: ["HotelName"] }; searchResults = await searchClient.search("sublime cliff", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 4 console.log('Query #4 - limit searchFields and use facets:'); searchOptions = { facets: ["Category"], select: ["HotelId", "HotelName", "Rating"], searchFields: ["HotelName"] }; searchResults = await searchClient.search("*", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 5 console.log('Query #5 - Lookup document:'); let documentResult = await searchClient.getDocument('3'); console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`); console.log(); } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } main().catch((err) => { console.error("The sample encountered an error:", err); });
Buat file bernama hotels.json dan tempelkan kode berikut ke hotels.json:
{ "value": [ { "HotelId": "1", "HotelName": "Secret Point Motel", "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", "Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.", "Category": "Boutique", "Tags": ["pool", "air conditioning", "concierge"], "ParkingIncluded": false, "LastRenovationDate": "1970-01-18T00:00:00Z", "Rating": 3.6, "Address": { "StreetAddress": "677 5th Ave", "City": "New York", "StateProvince": "NY", "PostalCode": "10022" } }, { "HotelId": "2", "HotelName": "Twin Dome Motel", "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.", "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", "Category": "Boutique", "Tags": ["pool", "free wifi", "concierge"], "ParkingIncluded": "false", "LastRenovationDate": "1979-02-18T00:00:00Z", "Rating": 3.6, "Address": { "StreetAddress": "140 University Town Center Dr", "City": "Sarasota", "StateProvince": "FL", "PostalCode": "34243" } }, { "HotelId": "3", "HotelName": "Triple Landscape Hotel", "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.", "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", "Category": "Resort and Spa", "Tags": ["air conditioning", "bar", "continental breakfast"], "ParkingIncluded": "true", "LastRenovationDate": "2015-09-20T00:00:00Z", "Rating": 4.8, "Address": { "StreetAddress": "3393 Peachtree Rd", "City": "Atlanta", "StateProvince": "GA", "PostalCode": "30326" } }, { "HotelId": "4", "HotelName": "Sublime Cliff Hotel", "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.", "Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.", "Category": "Boutique", "Tags": ["concierge", "view", "24-hour front desk service"], "ParkingIncluded": true, "LastRenovationDate": "1960-02-06T00:00:00Z", "Rating": 4.6, "Address": { "StreetAddress": "7400 San Pedro Ave", "City": "San Antonio", "StateProvince": "TX", "PostalCode": "78216" } } ] }
Buat file bernama hotels_quickstart_index.json dan tempelkan kode berikut ke hotels_quickstart_index.json:
{ "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String", "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "Description_fr", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "fr.lucene" }, { "name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true }, { "name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true }, { "name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true }, { "name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true }, { "name": "Address", "type": "Edm.ComplexType", "fields": [ { "name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true }, { "name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true } ] } ], "suggesters": [ { "name": "sg", "searchMode": "analyzingInfixMatching", "sourceFields": [ "HotelName" ] } ] }
Masuk ke Azure dengan perintah berikut:
az login
Jalankan kode JavaScript dengan perintah berikut:
node index.js
Menjelaskan kode
Buat indeks
File hotels_quickstart_index.json menentukan cara kerja Azure AI Search dengan dokumen yang Anda muat di langkah berikutnya. Setiap bidang diidentifikasi oleh name
dan memiliki type
. Setiap bidang juga memiliki serangkaian atribut indeks yang menentukan apakah Pencarian Azure AI dapat mencari, memfilter, mengurutkan, dan faset pada bidang . Sebagian besar bidang adalah tipe data sederhana, tetapi beberapa, AddressType
seperti adalah tipe kompleks yang memungkinkan Anda membuat struktur data kaya dalam indeks Anda. Anda dapat membaca selengkapnya tentang tipe data dan atribut indeks yang didukung yang dijelaskan dalam Create Index (REST).
Dengan definisi indeks kami di tempat, kami ingin mengimpor hotels_quickstart_index.jsdi bagian atas index.js sehingga fungsi utama dapat mengakses definisi indeks.
const indexDefinition = require('./hotels_quickstart_index.json');
Dalam fungsi utama, kita kemudian membuat SearchIndexClient
, yang digunakan untuk membuat dan mengelola indeks untuk Azure AI Search.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Selanjutnya, kami ingin menghapus indeks jika sudah ada. Operasi ini adalah praktik umum untuk kode uji/demo.
Kami melakukan ini dengan mendefinisikan fungsi sederhana yang mencoba menghapus indeks.
async function deleteIndexIfExists(indexClient, indexName) {
try {
await indexClient.deleteIndex(indexName);
console.log('Deleting index...');
} catch {
console.log('Index does not exist yet.');
}
}
Untuk menjalankan fungsi, kami mengekstrak nama indeks dari definisi indeks dan meneruskan indexName
bersama dengan indexClient
ke fungsi deleteIndexIfExists()
.
const indexName = indexDefinition["name"];
console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);
Setelah itu, kami siap membuat indeks dengan metode createIndex()
tersebut.
console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);
console.log(`Index named ${index.name} has been created.`);
Muat dokumen
Di Azure AI Search, dokumen adalah struktur data yang merupakan input ke pengindeksan dan output dari kueri. Anda dapat mendorong data tersebut ke indeks atau menggunakan pengindeks. Dalam hal ini, kami akan secara terprogram mendorong dokumen ke indeks.
Input dokumen mungkin baris dalam database, gumpalan dalam penyimpanan Blob, atau, seperti dalam sampel ini, dokumen JSON pada disk. Mirip dengan apa yang kita lakukan dengan indexDefinition
, kita juga perlu mengimpor hotels.json
di bagian atas index.js sehingga data dapat diakses dalam fungsi utama kita.
const hotelData = require('./hotels.json');
Untuk mengindeks data ke dalam indeks pencarian, kita sekarang perlu membuat SearchClient
. Saat SearchIndexClient
digunakan untuk membuat dan mengelola indeks, SearchClient
digunakan untuk mengunggah dokumen dan mengkueri indeks.
Ada dua cara untuk mencapai hal iniSearchClient
. Opsi pertama adalah membuat dari SearchClient
awal:
const searchClient = new SearchClient(endpoint, indexName, new AzureKeyCredential(apiKey));
Atau, Anda dapat menggunakan getSearchClient()
metode SearchIndexClient
untuk membuat SearchClient
:
const searchClient = indexClient.getSearchClient(indexName);
Sekarang setelah klien didefinisikan, unggah dokumen ke dalam indeks pencarian. Dalam hal ini, kami menggunakan mergeOrUploadDocuments()
metode , yang mengunggah dokumen atau menggabungkannya dengan dokumen yang ada jika dokumen dengan kunci yang sama sudah ada.
console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Mencari indeks
Dengan indeks dibuat dan dokumen diunggah, Anda siap untuk mengirim kueri ke indeks. Di bagian ini, kami mengirim lima kueri berbeda ke indeks pencarian untuk menunjukkan berbagai bagian fungsi kueri yang tersedia untuk Anda.
Kueri ditulis dalam sendQueries()
fungsi yang kita sebut dalam fungsi utama sebagai berikut:
await sendQueries(searchClient);
Kueri dikirim menggunakan metode search()
searchClient
. Parameter pertama adalah teks pencarian dan parameter kedua menentukan opsi pencarian.
Contoh kueri 1
Pencarian kueri pertama *
, yang setara dengan mencari semuanya dan memilih tiga bidang dalam indeks. Ada baiknya untuk select
hanya bidang yang Anda butuhkan karena menarik kembali data yang tidak perlu dapat menambah latensi ke kueri Anda.
searchOptions
untuk kueri ini juga telah includeTotalCount
diatur ke true
, yang mengembalikan jumlah hasil yang cocok yang ditemukan.
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
}
Kueri yang tersisa yang diuraikan di bawah ini juga harus ditambahkan ke fungsi sendQueries()
. Mereka dipisahkan di sini untuk keterbacaan.
Contoh kueri 2
Dalam kueri berikutnya, kami menentukan istilah pencarian "wifi"
dan juga menyertakan filter untuk hanya mengembalikan hasil dengan status yang sama dengan 'FL'
. Hasilnya juga dipesan oleh Rating
Hotel.
console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: ["HotelId", "HotelName", "Rating"]
};
searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Contoh kueri 3
Selanjutnya, pencarian dibatasi untuk satu bidang yang dapat dicari menggunakan parameter searchFields
. Pendekatan ini adalah opsi yang bagus untuk membuat kueri Anda lebih efisien jika Anda tahu bahwa Anda hanya tertarik pada kecocokan di bidang tertentu.
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();
Contoh kueri 4
Opsi umum lain untuk disertakan dalam kueri adalah facets
. Faset memungkinkan Anda membangun filter di UI untuk memudahkan pengguna mengetahui nilai yang dapat mereka filter.
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)}`);
}
Contoh kueri 5
Kueri akhir menggunakan getDocument()
metode searchClient
. Ini memungkinkan Anda untuk secara efisien mengambil dokumen dengan kuncinya.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Ringkasan kueri
Permintaan sebelumnya memperlihatkan beberapa cara pencocokan istilah dalam permintaan:pencarian teks lengkap, filter, dan kelengkapan otomatis.
Pencarian teks lengkap dan filter dilakukan menggunakan searchClient.search
metode . Kueri pencarian dapat diteruskan dalam searchText
string, sementara ekspresi filter dapat diteruskan di filter
properti SearchOptions
kelas. Untuk memfilter tanpa mencari, cukup teruskan "*" untuk searchText
parameter search
metode . Untuk mencari tanpa pemfilteran, biarkan filter
properti tidak diatur, atau tidak meneruskan SearchOptions
instans sama sekali.
Pelajari cara menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian menggunakan data sampel untuk pencarian teks lengkap. Pencarian teks lengkap menggunakan Apache Lucene untuk pengindeksan dan kueri, dan algoritma peringkat BM25 untuk hasil penilaian.
Mulai cepat ini membuat dan mengkueri indeks mulai cepat hotel kecil yang berisi data tentang empat hotel.
Tip
Anda dapat mengunduh dan menjalankan buku catatan yang sudah selesai.
Prasyarat
- Langganan Azure aktif - Buat langganan secara gratis
- Azure AI layanan Pencarian. Buat layanan jika Anda tidak memilikinya. Anda dapat menggunakan tingkat gratis untuk mulai cepat ini.
- Visual Studio Code dengan ekstensi Python, atau IDE yang setara, dengan Python 3.10 atau yang lebih baru. Jika Anda tidak memiliki versi Python yang sesuai yang terinstal, Anda dapat mengikuti instruksi dalam Tutorial Python Visual Studio Code.
Prasyarat ID Microsoft Entra
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, Anda perlu:
- Instal Azure CLI yang digunakan untuk autentikasi tanpa kunci dengan ID Microsoft Entra.
- Tetapkan peran
Search Service Contributor
danSearch Index Data Contributor
ke akun pengguna Anda. Anda dapat menetapkan peran dalam portal Azure di bawah Kontrol akses (IAM)>Menambahkan penetapan peran. Untuk informasi selengkapnya, lihat Menyambungkan ke Pencarian Azure AI menggunakan peran.
Mengambil informasi sumber daya
Anda perlu mengambil informasi berikut untuk mengautentikasi aplikasi Anda dengan Layanan Pencarian Azure AI Anda:
Nama variabel | Nilai |
---|---|
SEARCH_API_ENDPOINT |
Nilai ini dapat ditemukan di portal Azure. Pilih layanan pencarian Anda lalu dari menu sebelah kiri, pilih Gambaran Umum. Nilai Url di bawah Essentials adalah titik akhir yang Anda butuhkan. Contoh titik akhir mungkin terlihat sepertihttps://mydemo.search.windows.net . |
Pelajari selengkapnya tentang autentikasi tanpa kunci dan mengatur variabel lingkungan.
Menyiapkan lingkungan Anda
Anda menjalankan kode sampel di notebook Jupyter. Jadi, Anda perlu menyiapkan lingkungan Anda untuk menjalankan notebook Jupyter.
Unduh atau salin contoh buku catatan dari GitHub.
Buka buku catatan di Visual Studio Code.
Buat lingkungan Python baru untuk digunakan untuk menginstal paket yang Anda butuhkan untuk tutorial ini.
Penting
Jangan instal paket ke dalam penginstalan python global Anda. Anda harus selalu menggunakan lingkungan virtual atau conda saat menginstal paket python, jika tidak, Anda dapat memutuskan penginstalan global Python Anda.
Dibutuhkan waktu satu menit untuk mengatur. Jika Anda mengalami masalah, lihat lingkungan Python di Visual Studio Code.
Instal notebook Jupyter dan buku catatan IPython Kernel for Jupyter jika Anda belum memilikinya.
pip install jupyter pip install ipykernel python -m ipykernel install --user --name=.venv
Pilih kernel buku catatan.
- Di sudut kanan atas buku catatan, pilih Pilih Kernel.
- Jika Anda melihat
.venv
dalam daftar, pilihlah. Jika Anda tidak melihatnya, pilih Pilih Lingkungan.venv
> Python Kernel>Lain.
Membuat, memuat, dan mengkueri indeks pencarian
Di bagian ini, Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol. Untuk penjelasan terperinci tentang kode, lihat bagian menjelaskan kode .
Pastikan buku catatan terbuka di kernel
.venv
seperti yang dijelaskan di bagian sebelumnya.Jalankan sel kode pertama untuk menginstal paket yang diperlukan, termasuk azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet ! pip install azure-identity --quiet ! pip install python-dotenv --quiet
Ganti konten sel kode kedua dengan kode berikut tergantung pada metode autentikasi Anda.
Catatan
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti
DefaultAzureCredential
objek denganAzureKeyCredential
objek.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"
Hapus dua baris berikut dari sel Buat kode indeks . Kredensial sudah diatur di sel kode sebelumnya.
from azure.core.credentials import AzureKeyCredential credential = AzureKeyCredential(search_api_key)
Jalankan sel Buat kode indeks untuk membuat indeks pencarian.
Jalankan sel kode yang tersisa secara berurutan untuk memuat dokumen dan menjalankan kueri.
Menjelaskan kode
Buat indeks
SearchIndexClient
digunakan untuk membuat dan mengelola indeks untuk Azure AI Search. Setiap bidang diidentifikasi oleh name
dan memiliki type
.
Setiap bidang juga memiliki serangkaian atribut indeks yang menentukan apakah Pencarian Azure AI dapat mencari, memfilter, mengurutkan, dan faset pada bidang . Sebagian besar bidang adalah tipe data sederhana, tetapi beberapa, AddressType
seperti adalah tipe kompleks yang memungkinkan Anda membuat struktur data kaya dalam indeks Anda. Anda dapat membaca selengkapnya tentang tipe data dan atribut indeks yang didukung yang dijelaskan dalam Create Index (REST).
Membuat payload dokumen dan mengunggah dokumen
Gunakan tindakan indeks untuk jenis operasi, seperti unggah atau gabungkan dan unggah. Dokumen berasal dari sampel HotelsData di GitHub.
Mencari indeks
Anda bisa mendapatkan hasil kueri segera setelah dokumen pertama diindeks, tetapi pengujian aktual indeks Anda harus menunggu hingga semua dokumen diindeks.
Gunakan metode pencarian kelas search.client.
Contoh kueri dalam buku catatan adalah:
- Kueri dasar: Menjalankan pencarian kosong (
search=*
), mengembalikan daftar yang tidak dirankit (skor pencarian = 1,0) dari dokumen arbitrer. Karena tidak ada kriteria, semua dokumen disertakan dalam hasil. - Kueri istilah: Menambahkan seluruh istilah ke ekspresi pencarian ("wifi"). Kueri ini menentukan bahwa hasil hanya berisi bidang tersebut dalam pernyataan
select
. Membatasi bidang yang kembali akan meminimalkan jumlah data yang dikirim kembali melalui kabel dan mengurangi latensi pencarian. - Kueri yang difilter: Tambahkan ekspresi filter, hanya menampilkan hotel-hotel dengan peringkat yang lebih besar dari empat, diurutkan dalam urutan menurun.
- Cakupan bidang: Tambahkan
search_fields
ke eksekusi kueri cakupan ke bidang tertentu. - Faset: Hasilkan faset untuk kecocokan positif yang ditemukan di hasil pencarian. Tidak ada kecocokan nol. Jika hasil pencarian tidak menyertakan istilah wifi, maka wifi tidak muncul di struktur navigasi tersaring.
- Mencari dokumen: Mengembalikan dokumen berdasarkan kuncinya. Operasi ini berguna jika Anda ingin memberikan penelusuran saat pengguna memilih item dalam hasil pencarian.
- Pelengkapan otomatis: Berikan potensi kecocokan sebagai jenis pengguna ke dalam kotak pencarian. Pelengkapan otomatis menggunakan pemberi saran (
sg
) untuk mengetahui bidang mana yang berisi potensi kecocokan dengan permintaan pemberi saran. Dalam mulai cepat ini, bidang tersebut adalahTags
, ,Address/City
Address/Country
. Untuk mensimulasikan pelengkapan otomatis, berikan huruf sa sebagai string parsial. Metode pelengkapan otomatis SearchClient mengirimkan kembali potensi kecocokan istilah.
Menghapus indeks
Jika Anda sudah selesai dengan indeks ini, Anda dapat menghapusnya dengan menjalankan sel Bersihkan kode. Menghapus indeks yang tidak perlu mengosongkan ruang untuk melangkah melalui lebih banyak mulai cepat dan tutorial.
Pelajari cara menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian menggunakan data sampel untuk pencarian teks lengkap. Pencarian teks lengkap menggunakan Apache Lucene untuk pengindeksan dan kueri, dan algoritma peringkat BM25 untuk hasil penilaian.
Mulai cepat ini membuat dan mengkueri indeks mulai cepat hotel kecil yang berisi data tentang empat hotel.
Tip
Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Prasyarat
- Langganan Azure aktif - Buat langganan secara gratis
- Azure AI layanan Pencarian. Buat layanan jika Anda tidak memilikinya. Anda dapat menggunakan tingkat gratis untuk mulai cepat ini.
Prasyarat ID Microsoft Entra
Untuk autentikasi tanpa kunci yang direkomendasikan dengan ID Microsoft Entra, Anda perlu:
- Instal Azure CLI yang digunakan untuk autentikasi tanpa kunci dengan ID Microsoft Entra.
- Tetapkan peran
Search Service Contributor
danSearch Index Data Contributor
ke akun pengguna Anda. Anda dapat menetapkan peran dalam portal Azure di bawah Kontrol akses (IAM)>Menambahkan penetapan peran. Untuk informasi selengkapnya, lihat Menyambungkan ke Pencarian Azure AI menggunakan peran.
Mengambil informasi sumber daya
Anda perlu mengambil informasi berikut untuk mengautentikasi aplikasi Anda dengan Layanan Pencarian Azure AI Anda:
Nama variabel | Nilai |
---|---|
SEARCH_API_ENDPOINT |
Nilai ini dapat ditemukan di portal Azure. Pilih layanan pencarian Anda lalu dari menu sebelah kiri, pilih Gambaran Umum. Nilai Url di bawah Essentials adalah titik akhir yang Anda butuhkan. Contoh titik akhir mungkin terlihat sepertihttps://mydemo.search.windows.net . |
Pelajari selengkapnya tentang autentikasi tanpa kunci dan mengatur variabel lingkungan.
Penyiapan
Buat folder
full-text-quickstart
baru untuk berisi aplikasi dan buka Visual Studio Code di folder tersebut dengan perintah berikut:mkdir full-text-quickstart && cd full-text-quickstart
package.json
Buat dengan perintah berikut:npm init -y
package.json
Perbarui ke ECMAScript dengan perintah berikut:npm pkg set type=module
Instal pustaka klien Azure AI Search (Azure.Search.Documents) untuk JavaScript dengan:
npm install @azure/search-documents
Untuk autentikasi tanpa kata sandi yang direkomendasikan , instal pustaka klien Azure Identity dengan:
npm install @azure/identity
Membuat, memuat, dan mengkueri indeks pencarian
Di bagian penyetelan sebelumnya, Anda menginstal pustaka klien Azure AI Search dan dependensi lainnya.
Di bagian ini, Anda menambahkan kode untuk membuat indeks pencarian, memuatnya dengan dokumen, dan menjalankan kueri. Anda menjalankan program untuk melihat hasilnya di konsol. Untuk penjelasan terperinci tentang kode, lihat bagian menjelaskan kode .
Kode sampel dalam mulai cepat ini menggunakan ID Microsoft Entra untuk autentikasi tanpa kunci yang direkomendasikan. Jika Anda lebih suka menggunakan kunci API, Anda dapat mengganti DefaultAzureCredential
objek dengan AzureKeyCredential
objek.
const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/";
const credential = new DefaultAzureCredential();
Buat file baru bernama index.ts dan tempelkan kode berikut ke dalam index.ts:
// Import from the @azure/search-documents library import { SearchIndexClient, SearchClient, SearchFieldDataType, AzureKeyCredential, odata, SearchIndex } from "@azure/search-documents"; // Import from the Azure Identity library import { DefaultAzureCredential } from "@azure/identity"; // Importing the hotels sample data import hotelData from './hotels.json' assert { type: "json" }; // Load the .env file if it exists import * as dotenv from "dotenv"; dotenv.config(); // Defining the index definition const indexDefinition: SearchIndex = { "name": "hotels-quickstart", "fields": [ { "name": "HotelId", "type": "Edm.String" as SearchFieldDataType, "key": true, "filterable": true }, { "name": "HotelName", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": false, "sortable": true, "facetable": false }, { "name": "Description", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "en.lucene" }, { "name": "Description_fr", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzerName": "fr.lucene" }, { "name": "Category", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true }, { "name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true }, { "name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true }, { "name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true }, { "name": "Address", "type": "Edm.ComplexType", "fields": [ { "name": "StreetAddress", "type": "Edm.String" as SearchFieldDataType, "filterable": false, "sortable": false, "facetable": false, "searchable": true }, { "name": "City", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "StateProvince", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "PostalCode", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": true, "sortable": true, "facetable": true }, { "name": "Country", "type": "Edm.String" as SearchFieldDataType, "searchable": true, "filterable": true, "sortable": true, "facetable": true } ] } ], "suggesters": [ { "name": "sg", "searchMode": "analyzingInfixMatching", "sourceFields": [ "HotelName" ] } ] }; async function main() { // Your search service endpoint const searchServiceEndpoint = "https://<Put your search service NAME here>.search.windows.net/"; // Use the recommended keyless credential instead of the AzureKeyCredential credential. const credential = new DefaultAzureCredential(); //const credential = new AzureKeyCredential(Your search service admin key); // Create a SearchIndexClient to send create/delete index commands const searchIndexClient: SearchIndexClient = new SearchIndexClient( searchServiceEndpoint, credential ); // Creating a search client to upload documents and issue queries const indexName: string = "hotels-quickstart"; const searchClient: SearchClient<any> = searchIndexClient.getSearchClient(indexName); console.log('Checking if index exists...'); await deleteIndexIfExists(searchIndexClient, indexName); console.log('Creating index...'); let index: SearchIndex = await searchIndexClient.createIndex(indexDefinition); console.log(`Index named ${index.name} has been created.`); console.log('Uploading documents...'); let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']); console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `); // waiting one second for indexing to complete (for demo purposes only) sleep(1000); console.log('Querying the index...'); console.log(); await sendQueries(searchClient); } async function deleteIndexIfExists(searchIndexClient: SearchIndexClient, indexName: string) { try { await searchIndexClient.deleteIndex(indexName); console.log('Deleting index...'); } catch { console.log('Index does not exist yet.'); } } async function sendQueries(searchClient: SearchClient<any>) { // Query 1 console.log('Query #1 - search everything:'); let searchOptions: any = { includeTotalCount: true, select: ["HotelId", "HotelName", "Rating"] }; let searchResults = await searchClient.search("*", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(`Result count: ${searchResults.count}`); console.log(); // Query 2 console.log('Query #2 - search with filter, orderBy, and select:'); let state = 'FL'; searchOptions = { filter: odata`Address/StateProvince eq ${state}`, orderBy: ["Rating desc"], select: ["HotelId", "HotelName", "Rating"] }; searchResults = await searchClient.search("wifi", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 3 console.log('Query #3 - limit searchFields:'); searchOptions = { select: ["HotelId", "HotelName", "Rating"], searchFields: ["HotelName"] }; searchResults = await searchClient.search("sublime cliff", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 4 console.log('Query #4 - limit searchFields and use facets:'); searchOptions = { facets: ["Category"], select: ["HotelId", "HotelName", "Rating"], searchFields: ["HotelName"] }; searchResults = await searchClient.search("*", searchOptions); for await (const result of searchResults.results) { console.log(`${JSON.stringify(result.document)}`); } console.log(); // Query 5 console.log('Query #5 - Lookup document:'); let documentResult = await searchClient.getDocument('3'); console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`); console.log(); } function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } main().catch((err) => { console.error("The sample encountered an error:", err); });
Buat file bernama hotels.json dan tempelkan kode berikut ke hotels.json:
{ "value": [ { "HotelId": "1", "HotelName": "Secret Point Motel", "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.", "Description_fr": "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.", "Category": "Boutique", "Tags": ["pool", "air conditioning", "concierge"], "ParkingIncluded": false, "LastRenovationDate": "1970-01-18T00:00:00Z", "Rating": 3.6, "Address": { "StreetAddress": "677 5th Ave", "City": "New York", "StateProvince": "NY", "PostalCode": "10022" } }, { "HotelId": "2", "HotelName": "Twin Dome Motel", "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.", "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", "Category": "Boutique", "Tags": ["pool", "free wifi", "concierge"], "ParkingIncluded": "false", "LastRenovationDate": "1979-02-18T00:00:00Z", "Rating": 3.6, "Address": { "StreetAddress": "140 University Town Center Dr", "City": "Sarasota", "StateProvince": "FL", "PostalCode": "34243" } }, { "HotelId": "3", "HotelName": "Triple Landscape Hotel", "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.", "Description_fr": "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", "Category": "Resort and Spa", "Tags": ["air conditioning", "bar", "continental breakfast"], "ParkingIncluded": "true", "LastRenovationDate": "2015-09-20T00:00:00Z", "Rating": 4.8, "Address": { "StreetAddress": "3393 Peachtree Rd", "City": "Atlanta", "StateProvince": "GA", "PostalCode": "30326" } }, { "HotelId": "4", "HotelName": "Sublime Cliff Hotel", "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.", "Description_fr": "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.", "Category": "Boutique", "Tags": ["concierge", "view", "24-hour front desk service"], "ParkingIncluded": true, "LastRenovationDate": "1960-02-06T00:00:00Z", "Rating": 4.6, "Address": { "StreetAddress": "7400 San Pedro Ave", "City": "San Antonio", "StateProvince": "TX", "PostalCode": "78216" } } ] }
tsconfig.json
Buat file untuk menerjemahkan kode TypeScript dan salin kode berikut untuk ECMAScript.{ "compilerOptions": { "module": "NodeNext", "target": "ES2022", // Supports top-level await "moduleResolution": "NodeNext", "skipLibCheck": true, // Avoid type errors from node_modules "strict": true // Enable strict type-checking options }, "include": ["*.ts"] }
Transpile dari TypeScript ke JavaScript.
tsc
Masuk ke Azure dengan perintah berikut:
az login
Jalankan kode JavaScript dengan perintah berikut:
node index.js
Menjelaskan kode
Buat indeks
Membuat file hotels_quickstart_index.jsdi. File ini menentukan cara kerja Azure AI Search dengan dokumen yang Anda muat di langkah berikutnya. Setiap bidang diidentifikasi oleh name
dan memiliki type
. Setiap bidang juga memiliki serangkaian atribut indeks yang menentukan apakah Pencarian Azure AI dapat mencari, memfilter, mengurutkan, dan faset pada bidang . Sebagian besar bidang adalah tipe data sederhana, tetapi beberapa, AddressType
seperti adalah tipe kompleks yang memungkinkan Anda membuat struktur data kaya dalam indeks Anda. Anda dapat membaca selengkapnya tentang tipe data dan atribut indeks yang didukung yang dijelaskan dalam Create Index (REST).
Kami ingin mengimpor hotels_quickstart_index.json sehingga fungsi utama dapat mengakses definisi indeks.
import indexDefinition from './hotels_quickstart_index.json';
interface HotelIndexDefinition {
name: string;
fields: SimpleField[] | ComplexField[];
suggesters: SearchSuggester[];
};
const hotelIndexDefinition: HotelIndexDefinition = indexDefinition as HotelIndexDefinition;
Dalam fungsi utama, kita kemudian membuat SearchIndexClient
, yang digunakan untuk membuat dan mengelola indeks untuk Azure AI Search.
const indexClient = new SearchIndexClient(endpoint, new AzureKeyCredential(apiKey));
Selanjutnya, kami ingin menghapus indeks jika sudah ada. Operasi ini adalah praktik umum untuk kode uji/demo.
Kami melakukan ini dengan mendefinisikan fungsi sederhana yang mencoba menghapus 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.');
}
}
Untuk menjalankan fungsi, kami mengekstrak nama indeks dari definisi indeks dan meneruskan indexName
bersama dengan indexClient
ke fungsi 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);
Setelah itu, kami siap membuat indeks dengan metode createIndex()
tersebut.
console.log('Creating index...');
let index = await indexClient.createIndex(hotelIndexDefinition);
console.log(`Index named ${index.name} has been created.`);
Muat dokumen
Di Azure AI Search, dokumen adalah struktur data yang merupakan input ke pengindeksan dan output dari kueri. Anda dapat mendorong data tersebut ke indeks atau menggunakan pengindeks. Dalam hal ini, kami akan secara terprogram mendorong dokumen ke indeks.
Input dokumen mungkin baris dalam database, gumpalan dalam penyimpanan Blob, atau, seperti dalam sampel ini, dokumen JSON pada disk. Anda dapat mengunduh hotels.js atau membuat file hotels.js Anda sendiri dengan konten berikut:
Mirip dengan apa yang kita lakukan dengan indexDefinition, kita juga perlu mengimpor hotels.json
di bagian atas index.ts sehingga data dapat diakses dalam fungsi utama kita.
import hotelData from './hotels.json';
interface Hotel {
HotelId: string;
HotelName: string;
Description: string;
Description_fr: string;
Category: string;
Tags: string[];
ParkingIncluded: string | boolean;
LastRenovationDate: string;
Rating: number;
Address: {
StreetAddress: string;
City: string;
StateProvince: string;
PostalCode: string;
};
};
const hotels: Hotel[] = hotelData["value"];
Untuk mengindeks data ke dalam indeks pencarian, kita sekarang perlu membuat SearchClient
. Saat SearchIndexClient
digunakan untuk membuat dan mengelola indeks, SearchClient
digunakan untuk mengunggah dokumen dan mengkueri indeks.
Ada dua cara untuk mencapai hal iniSearchClient
. Opsi pertama adalah membuat dari SearchClient
awal:
const searchClient = new SearchClient<Hotel>(endpoint, indexName, new AzureKeyCredential(apiKey));
Atau, Anda dapat menggunakan getSearchClient()
metode SearchIndexClient
untuk membuat SearchClient
:
const searchClient = indexClient.getSearchClient<Hotel>(indexName);
Sekarang setelah klien didefinisikan, unggah dokumen ke dalam indeks pencarian. Dalam hal ini, kami menggunakan mergeOrUploadDocuments()
metode , yang mengunggah dokumen atau menggabungkannya dengan dokumen yang ada jika dokumen dengan kunci yang sama sudah ada. Kemudian periksa apakah operasi berhasil karena setidaknya dokumen pertama ada.
console.log("Uploading documents...");
const indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotels);
console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);
Jalankan program lagi dengan tsc && node index.ts
. Anda akan melihat sekumpulan pesan yang sedikit berbeda dari yang Anda lihat di Langkah 1. Kali ini, indeks memang ada, dan Anda akan melihat pesan tentang menghapusnya sebelum aplikasi membuat indeks baru dan memposting data ke dalamnya.
Sebelum kita menjalankan kueri di langkah berikutnya, tentukan fungsi agar program menunggu satu detik. Ini dilakukan hanya untuk tujuan pengujian / demo untuk memastikan penyelesaian pengindeksan dan bahwa dokumen tersedia dalam indeks untuk pertanyaan kami.
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
Agar program menunggu satu detik, panggil sleep
fungsi:
sleep(1000);
Mencari indeks
Dengan indeks dibuat dan dokumen diunggah, Anda siap untuk mengirim kueri ke indeks. Di bagian ini, kami mengirim lima kueri berbeda ke indeks pencarian untuk menunjukkan berbagai bagian fungsi kueri yang tersedia untuk Anda.
Kueri ditulis dalam sendQueries()
fungsi yang kita sebut dalam fungsi utama sebagai berikut:
await sendQueries(searchClient);
Kueri dikirim menggunakan metode search()
searchClient
. Parameter pertama adalah teks pencarian dan parameter kedua menentukan opsi pencarian.
Contoh kueri 1
Pencarian kueri pertama *
, yang setara dengan mencari semuanya dan memilih tiga bidang dalam indeks. Ada baiknya untuk select
hanya bidang yang Anda butuhkan karena menarik kembali data yang tidak perlu dapat menambah latensi ke kueri Anda.
searchOptions
untuk kueri ini juga telah includeTotalCount
diatur ke true
, yang akan mengembalikan jumlah hasil yang cocok yang ditemukan.
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
}
Kueri yang tersisa yang diuraikan di bawah ini juga harus ditambahkan ke fungsi sendQueries()
. Mereka dipisahkan di sini untuk keterbacaan.
Contoh kueri 2
Dalam kueri berikutnya, kami menentukan istilah pencarian "wifi"
dan juga menyertakan filter untuk hanya mengembalikan hasil dengan status yang sama dengan 'FL'
. Hasilnya juga dipesan oleh Rating
Hotel.
console.log('Query #2 - search with filter, orderBy, and select:');
let state = 'FL';
const searchOptions2 = {
filter: odata`Address/StateProvince eq ${state}`,
orderBy: ["Rating desc"],
select: selectFields
};
searchResults = await searchClient.search("wifi", searchOptions2);
for await (const result of searchResults.results) {
console.log(`${JSON.stringify(result.document)}`);
}
Contoh kueri 3
Selanjutnya, pencarian dibatasi untuk satu bidang yang dapat dicari menggunakan parameter searchFields
. Pendekatan ini adalah opsi yang bagus untuk membuat kueri Anda lebih efisien jika Anda tahu bahwa Anda hanya tertarik pada kecocokan di bidang tertentu.
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)}`);
}
Contoh kueri 4
Opsi umum lain untuk disertakan dalam kueri adalah facets
. Faset memungkinkan Anda untuk memberikan penelusuran yang diarahkan sendiri dari hasil di UI Anda. Hasil faset dapat diubah menjadi kotak centang di panel hasil.
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)}`);
}
Contoh kueri 5
Kueri akhir menggunakan getDocument()
metode searchClient
. Ini memungkinkan Anda untuk secara efisien mengambil dokumen dengan kuncinya.
console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)
Ringkasan kueri
Permintaan sebelumnya memperlihatkan beberapa cara pencocokan istilah dalam permintaan:pencarian teks lengkap, filter, dan kelengkapan otomatis.
Pencarian teks lengkap dan filter dilakukan menggunakan searchClient.search
metode . Kueri pencarian dapat diteruskan dalam searchText
string, sementara ekspresi filter dapat diteruskan di filter
properti SearchOptions
kelas. Untuk memfilter tanpa mencari, cukup teruskan "*" untuk searchText
parameter search
metode . Untuk mencari tanpa pemfilteran, biarkan filter
properti tidak diatur, atau tidak meneruskan SearchOptions
instans sama sekali.
Membersihkan sumber daya
Saat bekerja dengan langganan Anda sendiri, sebaiknya identifikasi apakah Anda masih membutuhkan sumber daya yang Anda buat di akhir proyek. Sumber daya yang dibiarkan berjalan dapat menghabiskan uang Anda. Anda dapat menghapus sumber daya satu per satu atau menghapus grup sumber daya untuk menghapus seluruh rangkaian sumber daya.
Anda dapat menemukan dan mengelola sumber daya di portal Azure, menggunakan tautan Semua sumber daya atau Grup sumber daya di panel navigasi kiri.
Jika Anda menggunakan layanan gratis, ingatlah bahwa Anda terbatas pada tiga indeks, pengindeks, dan sumber data. Anda dapat menghapus item individual di portal Azure agar tetap di bawah batas.
Langkah selanjutnya
Dalam mulai cepat ini, Anda bekerja melalui serangkaian tugas untuk membuat indeks, memuatnya dengan dokumen, dan menjalankan kueri. Pada tahap yang berbeda, pintasan diambil untuk menyederhanakan kode agar mudah dibaca dan dipahami. Sekarang setelah Anda terbiasa dengan konsep dasar, coba tutorial yang memanggil API Pencarian Azure AI di aplikasi web.