Pilih bahasa pemrograman untuk langkah berikutnya. Pustaka klien Azure.Search.Documents tersedia di Azure SDK untuk .NET, Python, Java, dan JavaScript/Typescript.
Buat aplikasi konsol menggunakan pustaka klien Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian.
Atau, Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Menyiapkan lingkungan Anda
Mulai Visual Studio dan buat proyek baru untuk aplikasi konsol.
Pada Tools>Paket Pengelolah NuGet , Pilih Kelola Paket NuGet Packages untuk Solusi....
Pilih Telusur.
Cari paket Azure.Search.Documents dan pilih versi 11.0 atau yang lebih baru.
Pilih Instal untuk menambahkan rakitan ke proyek dan solusi Anda.
Buat klien pencarian
Pada Program.cs, cubah namespace menjadi AzureSearch.SDK.Quickstart.v11
dan kemudian tambahkan yang berikut ini using
arahan.
using Azure;
using Azure.Search.Documents;
using Azure.Search.Documents.Indexes;
using Azure.Search.Documents.Indexes.Models;
using Azure.Search.Documents.Models;
Salin kode berikut untuk membuat dua klien. SearchIndexClient membuat indeks, dan SearchClient memuat dan mengkueri indeks yang ada. Keduanya memerlukan titik akhir layanan dan kunci API admin untuk autentikasi dengan hak buat/hapus.
Karena kode membangun URI untuk Anda, tentukan hanya nama layanan pencarian di serviceName
properti .
static void Main(string[] args)
{
string serviceName = "<your-search-service-name>";
string apiKey = "<your-search-service-admin-api-key>";
string indexName = "hotels-quickstart";
// Create a SearchIndexClient to send create/delete index commands
Uri serviceEndpoint = new Uri($"https://{serviceName}.search.windows.net/");
AzureKeyCredential credential = new AzureKeyCredential(apiKey);
SearchIndexClient adminClient = new SearchIndexClient(serviceEndpoint, credential);
// Create a SearchClient to load and query documents
SearchClient srchclient = new SearchClient(serviceEndpoint, indexName, credential);
. . .
}
Buat indeks
Panduan memulai ini membuat indeks Hotel yang akan Anda muat dengan data hotel dan menjalankan kueri. pada langkah ini, tentukan bidang dalam file index. 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.
Tambahkan definisi kelas kosong ke proyek Anda: Hotel.cs
Salin kode berikut ke dalam Hotel.cs 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; }
}
}
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 tipe data apa pun, selalu tidak dapat ditelusuri (diabaikan untuk kueri penelusuran teks lengkap), dan dapat diambil kembali (tidak disembunyikan). 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. 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.
Tambahkan definisi kelas kosong kedua ke proyek Anda: Address.cs. Salin kode berikut ke dalam kelas.
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 dua kelas lagi: Hotel.Methods.cs dan Address.Methods.cs untuk ToString()
penimpaan. Kelas-kelas ini digunakan untuk membuat hasil pencarian di keluaran konsol. Konten kelas ini tidak disediakan dalam artikel ini, tetapi Anda dapat menyalin kode dari file di GitHub.
Pada Program.cs, membuat obyek SearchIndex, dan kemudian memanggil metode CreateIndex untuk mengekspresikan indeks dalam 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 adminClient)
{
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);
adminClient.CreateOrUpdateIndex(definition);
}
Muat dokumen
Pencarian Azure AI mencari konten yang disimpan dalam layanan. Pada langkah ini, Anda akan memuat dokumen JSON yang sesuai dengan indeks hotel yang baru saja 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).
Pada Program.cs, buat larik dokumen dan tindakan indeks, lalu berikan larik 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"
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "2",
HotelName = "Old Century Hotel",
Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
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 = "Gastronomic 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 Palace Hotel",
Description = "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
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.",
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}");
}
}
Setelah Anda menginisialisasi IndexDocumentsBatch objek, Anda dapat mengirimkannya ke indeks dengan memanggil IndexDocuments pada obyek SearchClient Anda.
Tambahkan baris berikut ke Main()
. Pemuatan dokumen dilakukan menggunakan SearchClient, tetapi operasi juga memerlukan hak admin pada layanan, yang biasanya dikaitkan dengan SearchIndexClient. Salah satu cara untuk menyiapkan operasi ini adalah dengan mendapatkan SearchClient melalui SearchIndexClient
(adminClient
dalam contoh ini).
SearchClient ingesterClient = adminClient.GetSearchClient(indexName);
// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);
Karena ini adalah aplikasi konsol yang menjalankan semua perintah secara berurutan, tambahkan 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.
Di Program.cs, buat WriteDocuments
metode yang 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();
}
Buat RunQueries
metode untuk menjalankan kueri dan mengembalikan hasil. Hasilnya merupakan objek Hotel. Sampel ini menunjukkan metode tanda tangan dan permintaan pertama. Permintaan ini menunjukkan parameter terpilih yang memungkinkan anda untuk membuat hasil menggunakan bidang terpilih dari dokumen.
// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient srchclient)
{
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 = srchclient.Search<Hotel>("*", options);
WriteDocuments(response);
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 = srchclient.Search<Hotel>("hotels", options);
WriteDocuments(response);
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 = srchclient.Search<Hotel>("pool", options);
WriteDocuments(response);
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 = srchclient.Search<Hotel>("*", options);
WriteDocuments(response);
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 = srchclient.GetDocument<Hotel>("3");
Console.WriteLine(lookupResponse.Value.HotelId);
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 = srchclient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);
Tambahkan RunQueries
ke Main()
.
// Call the RunQueries method to invoke a series of queries
Console.WriteLine("Starting queries...\n");
RunQueries(srchclient);
// End the program
Console.WriteLine("{0}", "Complete. Press any key to end this program...\n");
Console.ReadKey();
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.
Jalankan program
Tekan F5 untuk membangun kembali aplikasi dan menjalankan program secara keseluruhan.
Output mencakup pesan dari Console.WriteLine, dengan penambahan informasi dan hasil permintaan.
Gunakan buku catatan Jupyter dan pustaka azure-search-documents di Azure SDK untuk Python untuk membuat, memuat, dan mengkueri indeks pencarian.
Atau, Anda dapat mengunduh dan menjalankan buku catatan yang sudah selesai.
Menyiapkan lingkungan Anda
Gunakan Visual Studio Code dengan ekstensi Python, atau IDE yang setara, dengan Python 3.10 atau yang lebih baru.
Kami merekomendasikan lingkungan virtual untuk mulai cepat ini:
Memulai Visual Studio Code.
Buka Palet Perintah (Ctrl+Shift+P).
Cari Python: Buat Lingkungan.
Pilih Venv.
Pilih interpreter Python. Pilih versi 3.10 atau yang lebih baru.
Dibutuhkan waktu satu menit untuk mengatur. Jika Anda mengalami masalah, lihat lingkungan Python di Visual Studio Code.
Menginstal paket dan mengatur variabel
Instal paket, termasuk azure-search-documents.
! pip install azure-search-documents==11.6.0b1 --quiet
! pip install azure-identity --quiet
! pip install python-dotenv --quiet
Berikan titik akhir dan kunci API untuk layanan Anda:
search_endpoint: str = "PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE"
search_api_key: str = "PUT-YOUR-SEARCH-SERVICE-ADMIN-API-KEY-HERE"
index_name: str = "hotels-quickstart"
Buat indeks
from azure.core.credentials import AzureKeyCredential
credential = AzureKeyCredential(search_api_key)
from azure.search.documents.indexes import SearchIndexClient
from azure.search.documents import SearchClient
from azure.search.documents.indexes.models import (
ComplexField,
SimpleField,
SearchFieldDataType,
SearchableField,
SearchIndex
)
# Create a search schema
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
fields = [
SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True),
SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
SearchableField(name="Description", type=SearchFieldDataType.String, analyzer_name="en.lucene"),
SearchableField(name="Description_fr", type=SearchFieldDataType.String, analyzer_name="fr.lucene"),
SearchableField(name="Category", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Tags", collection=True, type=SearchFieldDataType.String, facetable=True, filterable=True),
SimpleField(name="ParkingIncluded", type=SearchFieldDataType.Boolean, facetable=True, filterable=True, sortable=True),
SimpleField(name="LastRenovationDate", type=SearchFieldDataType.DateTimeOffset, facetable=True, filterable=True, sortable=True),
SimpleField(name="Rating", type=SearchFieldDataType.Double, facetable=True, filterable=True, sortable=True),
ComplexField(name="Address", fields=[
SearchableField(name="StreetAddress", type=SearchFieldDataType.String),
SearchableField(name="City", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="StateProvince", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="PostalCode", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
SearchableField(name="Country", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
])
]
scoring_profiles = []
suggester = [{'name': 'sg', 'source_fields': ['Tags', 'Address/City', 'Address/Country']}]
# Create the search index
index = SearchIndex(name=index_name, fields=fields, suggesters=suggester, scoring_profiles=scoring_profiles)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')
Membuat payload dokumen
Gunakan tindakan indeks untuk jenis operasi, seperti unggah atau gabungkan dan unggah. Dokumen berasal dari sampel HotelsData di GitHub.
# Create a documents payload
documents = [
{
"@search.action": "upload",
"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.",
"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.60,
"Address": {
"StreetAddress": "677 5th Ave",
"City": "New York",
"StateProvince": "NY",
"PostalCode": "10022",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "2",
"HotelName": "Old Century Hotel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"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.60,
"Address": {
"StreetAddress": "140 University Town Center Dr",
"City": "Sarasota",
"StateProvince": "FL",
"PostalCode": "34243",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "3",
"HotelName": "Gastronomic Landscape Hotel",
"Description": "The 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.80,
"Address": {
"StreetAddress": "3393 Peachtree Rd",
"City": "Atlanta",
"StateProvince": "GA",
"PostalCode": "30326",
"Country": "USA"
}
},
{
"@search.action": "upload",
"HotelId": "4",
"HotelName": "Sublime Palace Hotel",
"Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
"Description_fr": "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.",
"Category": "Boutique",
"Tags": [ "concierge", "view", "24-hour front desk service" ],
"ParkingIncluded": "true",
"LastRenovationDate": "1960-02-06T00:00:00Z",
"Rating": 4.60,
"Address": {
"StreetAddress": "7400 San Pedro Ave",
"City": "San Antonio",
"StateProvince": "TX",
"PostalCode": "78216",
"Country": "USA"
}
}
]
Unggah dokumen
# Upload documents to the index
search_client = SearchClient(endpoint=search_endpoint,
index_name=index_name,
credential=credential)
try:
result = search_client.upload_documents(documents=documents)
print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
print (ex.message)
index_client = SearchIndexClient(
endpoint=search_endpoint, credential=credential)
Menjalankan kueri pertama Anda
Gunakan metode pencarian kelas search.client.
Contoh ini 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.
# Run an empty query (returns selected fields, all documents)
results = search_client.search(query_type='simple',
search_text="*" ,
select='HotelName,Description',
include_total_count=True)
print ('Total Documents Matching Query:', results.get_count())
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Menjalankan kueri istilah
Kueri berikutnya akan 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.
results = search_client.search(query_type='simple',
search_text="wifi" ,
select='HotelName,Description,Tags',
include_total_count=True)
print ('Total Documents Matching Query:', results.get_count())
for result in results:
print(result["@search.score"])
print(result["HotelName"])
print(f"Description: {result['Description']}")
Menambahkan filter
Tambahkan ekspresi filter, mengembalikan hanya hotel-hotel tersebut dengan peringkat lebih besar dari empat, diurutkan dalam urutan menurun.
# Add a filter
results = search_client.search(
search_text="hotels",
select='HotelId,HotelName,Rating',
filter='Rating gt 4',
order_by='Rating desc')
for result in results:
print("{}: {} - {} rating".format(result["HotelId"], result["HotelName"], result["Rating"]))
Menambahkan cakupan bidang
Tambahkan search_fields
ke eksekusi kueri cakupan ke bidang tertentu.
# Add search_fields to scope query matching to the HotelName field
results = search_client.search(
search_text="sublime",
search_fields=['HotelName'],
select='HotelId,HotelName')
for result in results:
print("{}: {}".format(result["HotelId"], result["HotelName"]))
Menambahkan faset
Faset dihasilkan 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.
# Return facets
results = search_client.search(search_text="*", facets=["Category"])
facets = results.get_facets()
for facet in facets["Category"]:
print(" {}".format(facet))
Mencari dokumen
Mengembalikan dokumen berdasarkan kuncinya. Operasi ini berguna jika Anda ingin memberikan penelusuran saat pengguna memilih item dalam hasil pencarian.
# Look up a specific document by ID
result = search_client.get_document(key="3")
print("Details for hotel '3' are:")
print("Name: {}".format(result["HotelName"]))
print("Rating: {}".format(result["Rating"]))
print("Category: {}".format(result["Category"]))
Tambahkan lengkapiotomatis
Pelengkapan otomatis dapat memberikan 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 adalah Tags
, , Address/City
Address/Country
.
Untuk mensimulasikan pelengkapan otomatis, berikan huruf sa sebagai string parsial. Metode pelengkapan otomatis SearchClient mengirimkan kembali potensi kecocokan istilah.
# Autocomplete a query
search_suggestion = 'sa'
results = search_client.autocomplete(
search_text=search_suggestion,
suggester_name="sg",
mode='twoTerms')
print("Autocomplete for:", search_suggestion)
for result in results:
print (result['text'])
Buat aplikasi konsol Java menggunakan pustaka Azure.Search.Documents untuk membuat, memuat, dan mengkueri indeks pencarian.
Atau, Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Menyiapkan lingkungan Anda
Gunakan alat berikut untuk membuat mulai cepat ini.
Membuat proyek
Memulai Visual Studio Code.
Buka Palet Perintah dengan menggunakan Ctrl+Shift+P. Cari Buat Proyek Java.
Pilih Maven.
Pilih maven-archetype-quickstart.
Pilih versi terbaru, saat ini 1.4.
Masukkan azure.search.sample sebagai ID grup.
Masukkan azuresearchquickstart sebagai ID artefak.
Pilih folder untuk membuat proyek.
Selesaikan pembuatan proyek di terminal terintegrasi. Tekan enter untuk menerima default untuk "1.0-SNAPSHOT" lalu ketik "y" untuk mengonfirmasi properti untuk proyek Anda.
Buka folder tempat Anda membuat proyek.
Tentukan dependensi Maven
Buka file pom.xml dan tambahkan dependensi berikut.
<dependencies>
<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>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
Ubah versi Java pengkompilasi menjadi 11.
<maven.compiler.source>1.11</maven.compiler.source>
<maven.compiler.target>1.11</maven.compiler.target>
Buat klien pencarian
Buka kelas di App
bawah src, main, java, azure, search, sample. Tambahkan direktif impor berikut.
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.credential.AzureKeyCredential;
import com.azure.core.util.Context;
import com.azure.search.documents.SearchClient;
import com.azure.search.documents.SearchClientBuilder;
import com.azure.search.documents.models.SearchOptions;
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.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;
Contoh berikut mencakup tempat penampung untuk nama layanan pencarian, kunci API admin yang memberikan izin membuat dan menghapus, dan nama indeks. Ganti nilai yang valid untuk ketiga tempat penampung. Buat dua klien: SearchIndexClient membuat indeks, dan SearchClient memuat dan menanyakan indeks yang ada. Keduanya memerlukan titik akhir layanan dan kunci API admin untuk autentikasi dengan hak buat dan hapus.
public static void main(String[] args) {
var searchServiceEndpoint = "<YOUR-SEARCH-SERVICE-URL>";
var adminKey = new AzureKeyCredential("<YOUR-SEARCH-SERVICE-ADMIN-KEY>");
String indexName = "<YOUR-SEARCH-INDEX-NAME>";
SearchIndexClient searchIndexClient = new SearchIndexClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(adminKey)
.buildClient();
SearchClient searchClient = new SearchClientBuilder()
.endpoint(searchServiceEndpoint)
.credential(adminKey)
.indexName(indexName)
.buildClient();
}
Buat indeks
Panduan memulai ini membuat indeks Hotel yang akan Anda muat dengan data hotel dan menjalankan kueri. pada langkah ini, tentukan bidang dalam file index. 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 SearchAsyncClient alih-alih SearchClient.
Tambahkan definisi kelas kosong ke proyek Anda: Hotel.java
Salin kode berikut ke dalam Hotel.java
untuk menentukan struktur dokumen hotel. Atribut di bidang menentukan bagaimana atribut digunakan dalam aplikasi. Misalnya, anotasi IsFilterable harus ditetapkan ke setiap bidang yang mendukung ekspresi filter
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azure.search.sample;
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 "";
}
}
}
Di Pustaka klien Azure.Search.Documents, Anda dapat menggunakan SearchableField dan SimpleField untuk merampingkan definisi bidang.
SimpleField
dapat berupa tipe data apa pun, selalu tidak dapat ditelusuri (diabaikan untuk kueri penelusuran teks lengkap), dan dapat diambil kembali (tidak disembunyikan). 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.
Tambahkan definisi kelas kosong kedua ke proyek Anda: Address.java
. Salin kode berikut ke dalam kelas.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
package azure.search.sample;
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;
}
Di App.java
, buat SearchIndex
objek dalam main
metode , lalu panggil 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. Pada langkah ini, Anda akan memuat dokumen JSON yang sesuai dengan indeks hotel yang baru saja 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
, buat dokumen dan tindakan indeks, lalu teruskan 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)
{
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");
}
}
Setelah menginisialisasi IndexDocumentsBatch
objek, Anda dapat mengirimkannya ke indeks dengan memanggil indexDocuments pada objek Anda SearchClient
.
Tambahkan baris berikut ke Main()
. Memuat dokumen dilakukan menggunakan SearchClient
.
// Upload sample hotel documents to the Search Index
uploadDocuments(searchClient);
Karena ini adalah aplikasi konsol yang menjalankan semua perintah secara berurutan, tambahkan 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 kueri, dan hasil. Untuk pertanyaan, gunakan metode Cari. Metode ini mengambil teks pencarian (string kueri) dan opsi lainnya.
Di App.java
, buat WriteDocuments
metode yang 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();
}
Buat RunQueries
metode untuk menjalankan kueri dan mengembalikan hasil. Hasilnya adalah Hotel
objek. 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));
}
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));
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));
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));
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();
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"));
Tambahkan RunQueries
ke Main()
.
// 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");
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.
Jalankan program
Tekan F5 untuk membangun kembali aplikasi dan menjalankan program secara keseluruhan.
Output mencakup pesan dari System.out.println
, dengan penambahan informasi dan hasil kueri.
Buat aplikasi Node.js menggunakan pustaka dokumen @azure/pencarian untuk membuat, memuat, dan mengkueri indeks pencarian.
Atau, Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Menyiapkan lingkungan Anda
Kami menggunakan alat berikut untuk membuat mulai cepat ini.
Membuat proyek
Memulai Visual Studio Code.
Buka Palet Perintah dengan menggunakan Ctrl+Shift+P dan buka terminal terintegrasi.
Buat direktori pengembangan, beri nama mulai cepat:
mkdir quickstart
cd quickstart
Inisialisasi proyek kosong dengan npm dengan menjalankan perintah berikut. Untuk menginisialisasi proyek sepenuhnya, tekan Enter beberapa kali untuk menerima nilai default, kecuali untuk Lisensi, yang harus Anda atur ke MIT.
npm init
Instal @azure/search-documents
, JavaScript/TypeScript SDK untuk Azure AI Search.
npm install @azure/search-documents
Instal dotenv
, yang digunakan untuk mengimpor variabel lingkungan seperti nama layanan pencarian dan kunci API Anda.
npm install dotenv
Navigasikan ke direktori mulai cepat, lalu konfirmasikan bahwa Anda telah mengonfigurasi proyek dan dependensinya dengan memeriksa bahwa file package.json Anda terlihat mirip dengan json berikut:
{
"name": "quickstart",
"version": "1.0.0",
"description": "Azure AI Search Quickstart",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Azure",
"Search"
],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"@azure/search-documents": "^11.3.0",
"dotenv": "^16.0.2"
}
}
Buat file .env untuk menahan parameter layanan pencarian Anda:
SEARCH_API_KEY=<YOUR-SEARCH-ADMIN-API-KEY>
SEARCH_API_ENDPOINT=<YOUR-SEARCH-SERVICE-URL>
YOUR-SEARCH-SERVICE-URL
Ganti nilai dengan nama URL titik akhir layanan pencarian Anda. Ganti <YOUR-SEARCH-ADMIN-API-KEY>
dengan kunci admin yang Anda rekam sebelumnya.
Membuat index.js file
Selanjutnya kita membuat file index.js , yang merupakan file utama yang menghosting kode kita.
Di bagian atas file ini, kami mengimpor pustaka @azure/search-documents
:
const { SearchIndexClient, SearchClient, AzureKeyCredential, odata } = require("@azure/search-documents");
Selanjutnya, kita perlu mewajibkan dotenv
paket untuk membaca parameter dari file .env sebagai berikut:
// Load the .env file if it exists
require("dotenv").config();
// Getting endpoint and apiKey from .env file
const endpoint = process.env.SEARCH_API_ENDPOINT || "";
const apiKey = process.env.SEARCH_API_KEY || "";
Dengan impor dan variabel lingkungan kami di tempat, kami siap untuk mendefinisikan fungsi utama.
Sebagian besar fungsionalitas dalam SDK tidak sinkron sehingga kami membuat fungsi utama async
kami. Kami juga menyertakan fungsi main().catch()
utama di bawah ini untuk menangkap dan mencatat kesalahan yang dihadapi:
async function main() {
console.log(`Running Azure AI Search JavaScript quickstart...`);
if (!endpoint || !apiKey) {
console.log("Make sure to set valid values for endpoint and apiKey with proper authorization.");
return;
}
// remaining quickstart code will go here
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
Dengan itu di tempat, kami siap untuk membuat indeks.
Buat indeks
Membuat file hotels_quickstart_index.jsdi. File ini menentukan cara kerja Azure AI Search dengan dokumen yang akan Anda muat di langkah berikutnya. Setiap bidang akan diidentifikasi oleh name
dan memiliki type
yang ditentukan. 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).
Tambahkan konten berikut ke hotels_quickstart_index.json atau unduh file.
{
"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"
]
}
]
}
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.`);
Jalankan sampel
Pada titik ini, Anda siap untuk menjalankan sampel. Gunakan jendela terminal untuk menjalankan perintah berikut:
node index.js
Jika Anda mengunduh kode sumber danbelum menginstal paket yang diperlukan, jalankan npm install
terlebih dahulu.
Anda akan melihat serangkaian pesan yang menjelaskan tindakan yang diambil oleh program.
Buka Gambaran Umum layanan pencarian Anda di portal Azure. Pilih tab Indeks . Anda akan melihat sesuatu seperti contoh berikut:
Di langkah berikutnya, Anda akan menambahkan data ke indeks.
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:
{
"value": [
{
"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.",
"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": "Old Century Hotel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"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": "Gastronomic 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 Palace Hotel",
"Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
"Description_fr": "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.",
"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"
}
}
]
}
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)}`);
Jalankan program lagi dengan node index.js
. 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) {
var d = new Date();
var d2 = null;
do {
d2 = new Date();
} while (d2 - d < ms);
}
Agar program menunggu satu detik, hubungi fungsi sleep
seperti di bawah ini:
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.
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.
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)}`);
}
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();
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)}`);
}
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}`)
Jalankan sampel
Jalankan program dengan menggunakan node index.js
. Sekarang, selain langkah-langkah sebelumnya, kueri dikirim dan hasilnya ditulis ke konsol.
Buat aplikasi Node.js menggunakan pustaka dokumen @azure/pencarian untuk membuat, memuat, dan mengkueri indeks pencarian.
Atau, Anda dapat mengunduh kode sumber untuk memulai dengan proyek yang sudah selesai atau mengikuti langkah-langkah ini untuk membuat sendiri.
Menyiapkan lingkungan Anda
Kami menggunakan alat berikut untuk membuat mulai cepat ini.
Membuat proyek
Memulai Visual Studio Code.
Buka Palet Perintah dengan menggunakan Ctrl+Shift+P dan buka terminal terintegrasi.
Buat direktori pengembangan, beri nama mulai cepat:
mkdir quickstart
cd quickstart
Inisialisasi proyek kosong dengan npm dengan menjalankan perintah berikut. Untuk menginisialisasi proyek sepenuhnya, tekan Enter beberapa kali untuk menerima nilai default, kecuali untuk Lisensi, yang harus Anda atur ke MIT.
npm init
Instal @azure/search-documents
, JavaScript/TypeScript SDK untuk Azure AI Search.
npm install @azure/search-documents
Instal dotenv
, yang digunakan untuk mengimpor variabel lingkungan seperti nama layanan pencarian dan kunci API Anda.
npm install dotenv
Navigasikan ke direktori mulai cepat, lalu konfirmasikan bahwa Anda telah mengonfigurasi proyek dan dependensinya dengan memeriksa bahwa file package.json Anda terlihat mirip dengan json berikut:
{
"name": "quickstart",
"version": "1.0.0",
"description": "Azure AI Search Quickstart",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"Azure",
"Search"
],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"@azure/search-documents": "^12.1.0",
"dotenv": "^16.4.5"
}
}
Buat file .env untuk menahan parameter layanan pencarian Anda:
SEARCH_API_KEY=<YOUR-SEARCH-ADMIN-API-KEY>
SEARCH_API_ENDPOINT=<YOUR-SEARCH-SERVICE-URL>
YOUR-SEARCH-SERVICE-URL
Ganti nilai dengan nama URL titik akhir layanan pencarian Anda. Ganti <YOUR-SEARCH-ADMIN-API-KEY>
dengan kunci admin yang Anda rekam sebelumnya.
Membuat file index.ts
Selanjutnya kita membuat file index.ts , yang merupakan file utama yang menghosting kode kita.
Di bagian atas file ini, kami mengimpor pustaka @azure/search-documents
:
import {
AzureKeyCredential,
ComplexField,
odata,
SearchClient,
SearchFieldArray,
SearchIndex,
SearchIndexClient,
SearchSuggester,
SimpleField
} from "@azure/search-documents";
Selanjutnya, kita perlu mewajibkan dotenv
paket untuk membaca parameter dari file .env sebagai berikut:
// Load the .env file if it exists
import dotenv from 'dotenv';
dotenv.config();
// Getting endpoint and apiKey from .env file
const endpoint = process.env.SEARCH_API_ENDPOINT || "";
const apiKey = process.env.SEARCH_API_KEY || "";
Dengan impor dan variabel lingkungan kami di tempat, kami siap untuk mendefinisikan fungsi utama.
Sebagian besar fungsionalitas dalam SDK tidak sinkron sehingga kami membuat fungsi utama async
kami. Kami juga menyertakan fungsi main().catch()
utama di bawah ini untuk menangkap dan mencatat kesalahan yang dihadapi:
async function main() {
console.log(`Running Azure AI Search JavaScript quickstart...`);
if (!endpoint || !apiKey) {
console.log("Make sure to set valid values for endpoint and apiKey with proper authorization.");
return;
}
// remaining quickstart code will go here
}
main().catch((err) => {
console.error("The sample encountered an error:", err);
});
Dengan itu di tempat, kami siap untuk membuat indeks.
Buat indeks
Membuat file hotels_quickstart_index.jsdi. File ini menentukan cara kerja Azure AI Search dengan dokumen yang akan Anda muat di langkah berikutnya. Setiap bidang akan diidentifikasi oleh name
dan memiliki type
yang ditentukan. 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).
Tambahkan konten berikut ke hotels_quickstart_index.json atau unduh file.
{
"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"
]
}
]
}
Dengan definisi indeks kami di tempat, kami ingin mengimpor hotels_quickstart_index.json di bagian atas index.ts sehingga fungsi utama dapat mengakses definisi indeks.
// Importing the index definition and sample data
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.`);
Jalankan sampel
Pada titik ini, Anda siap untuk membangun dan menjalankan sampel. Gunakan jendela terminal untuk menjalankan perintah berikut untuk membangun sumber Anda, tsc
lalu jalankan sumber Anda dengan node
:
tsc
node index.ts
Jika Anda mengunduh kode sumber danbelum menginstal paket yang diperlukan, jalankan npm install
terlebih dahulu.
Anda akan melihat serangkaian pesan yang menjelaskan tindakan yang diambil oleh program.
Buka Gambaran Umum layanan pencarian Anda di portal Azure. Pilih tab Indeks . Anda akan melihat sesuatu seperti contoh berikut:
Di langkah berikutnya, Anda akan menambahkan data ke indeks.
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:
{
"value": [
{
"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.",
"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": "Old Century Hotel",
"Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.",
"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": "Gastronomic 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 Palace Hotel",
"Description": "Sublime Palace Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Palace is part of a lovingly restored 1800 palace.",
"Description_fr": "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.",
"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"
}
}
]
}
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.
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.
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)}`);
}
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)}`);
}
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)}`);
}
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}`)
Jalankan ulang sampel
Bangun dan jalankan program dengan tsc && node index.ts
. Sekarang, selain langkah-langkah sebelumnya, kueri dikirim dan hasilnya ditulis ke konsol.
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.
Jika Anda menggunakan layanan gratis, ingatlah bahwa Anda terbatas pada tiga indeks, pengindeks, dan sumber data. Anda dapat menghapus item individu di portal agar tetap berada dalam batasan.
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.