Membuat aplikasi pencarian di ASP.NET Core
Dalam tutorial ini, buat aplikasi dasar ASP.NET Core (Model-View-Controller) yang berjalan di localhost dan terhubung ke hotel-sample-index di layanan pencarian Anda. Dalam tutorial ini, Anda akan mempelajari cara:
- Membuat halaman pencarian dasar
- Memfilter hasil
- Urukan hasil
Tutorial ini menempatkan fokus pada operasi sisi server yang dipanggil melalui API Pencarian. Meskipun umum untuk mengurutkan dan memfilter dalam skrip sisi klien, mengetahui cara memanggil operasi ini di server memberi Anda lebih banyak opsi saat merancang pengalaman pencarian.
Kode sampel untuk tutorial ini dapat ditemukan di repositori azure-search-dotnet-samples di GitHub.
Prasyarat
- Visual Studio
- Paket NuGet Azure.Search.Documents
- Pencarian Azure AI, tingkat apa pun, tetapi harus memiliki akses jaringan publik.
- Indeks sampel hotel
Telusuri wizard Impor data untuk membuat indeks sampel hotel di layanan pencarian Anda. Atau, ubah nama indeks dalam HomeController.cs
file.
Membuat proyek
Mulai Visual Studio dan pilih Buat proyek baru.
Pilih ASP.NET Core Web App (Model-View-Controller), lalu pilih Berikutnya.
Berikan nama proyek, lalu pilih Berikutnya.
Pada halaman berikutnya, pilih .NET 6.0 atau .NET 7.0 atau .NET 8.0.
Verifikasi bahwa Jangan gunakan pernyataan tingkat atas tidak dicentang.
Pilih Buat.
Menambahkan paket NuGet
Pada Alat, pilih Manajer>Paket NuGet Kelola Paket NuGet untuk solusinya.
Telusuri
Azure.Search.Documents
dan instal versi stabil terbaru.Telusuri dan instal
Microsoft.Spatial
paket. Indeks sampel menyertakan jenis data GeographyPoint. Menginstal paket ini menghindari kesalahan run time. Atau, hapus bidang "Lokasi" dari kelas Hotel jika Anda tidak ingin menginstal paket. Bidang tersebut tidak digunakan dalam tutorial ini.
Menambahkan informasi layanan
Untuk koneksi, aplikasi menyajikan kunci API kueri ke URL pencarian Anda yang sepenuhnya memenuhi syarat. Keduanya ditentukan dalam appsettings.json
file.
Ubah appsettings.json
untuk menentukan layanan pencarian dan kunci API kueri Anda.
{
"SearchServiceUri": "<YOUR-SEARCH-SERVICE-URL>",
"SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-QUERY-API-KEY>"
}
Anda bisa mendapatkan URL layanan dan kunci API dari portal Azure. Karena kode ini mengkueri indeks dan tidak membuatnya, Anda bisa menggunakan kunci kueri alih-alih kunci admin.
Pastikan untuk menentukan layanan pencarian yang memiliki hotel-sample-index.
Menambahkan model
Dalam langkah ini, buat model yang mewakili skema hotel-sample-index.
Di Penjelajah solusi, pilih kanan Model dan tambahkan kelas baru bernama "Hotel" untuk kode berikut:
using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Indexes; using Microsoft.Spatial; using System.Text.Json.Serialization; namespace HotelDemoApp.Models { public partial class Hotel { [SimpleField(IsFilterable = true, IsKey = 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; } public Address Address { get; set; } [SimpleField(IsFilterable = true, IsSortable = true)] public GeographyPoint Location { get; set; } public Rooms[] Rooms { get; set; } } }
Tambahkan kelas bernama "Address" dan ganti dengan kode berikut:
using Azure.Search.Documents.Indexes; namespace HotelDemoApp.Models { public partial class Address { [SearchableField] 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; } } }
Tambahkan kelas bernama "Rooms" dan ganti dengan kode berikut:
using Azure.Search.Documents.Indexes.Models; using Azure.Search.Documents.Indexes; using System.Text.Json.Serialization; namespace HotelDemoApp.Models { public partial class Rooms { [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnMicrosoft)] public string Description { get; set; } [SearchableField(AnalyzerName = LexicalAnalyzerName.Values.FrMicrosoft)] [JsonPropertyName("Description_fr")] public string DescriptionFr { get; set; } [SearchableField(IsFilterable = true, IsFacetable = true)] public string Type { get; set; } [SimpleField(IsFilterable = true, IsFacetable = true)] public double? BaseRate { get; set; } [SearchableField(IsFilterable = true, IsFacetable = true)] public string BedOptions { get; set; } [SimpleField(IsFilterable = true, IsFacetable = true)] public int SleepsCount { get; set; } [SimpleField(IsFilterable = true, IsFacetable = true)] public bool? SmokingAllowed { get; set; } [SearchableField(IsFilterable = true, IsFacetable = true)] public string[] Tags { get; set; } } }
Tambahkan kelas bernama "SearchData" dan ganti dengan kode berikut:
using Azure.Search.Documents.Models; namespace HotelDemoApp.Models { public class SearchData { // The text to search for. public string searchText { get; set; } // The list of results. public SearchResults<Hotel> resultList; } }
Mengubah pengontrol
Untuk tutorial ini, ubah default HomeController
untuk berisi metode yang dijalankan pada layanan pencarian Anda.
Di Penjelajah solusi di bawah Model, buka
HomeController
.Ganti default dengan konten berikut:
using Azure; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using HotelDemoApp.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; namespace HotelDemoApp.Controllers { public class HomeController : Controller { public IActionResult Index() { return View(); } [HttpPost] public async Task<ActionResult> Index(SearchData model) { try { // Check for a search string if (model.searchText == null) { model.searchText = ""; } // Send the query to Search. await RunQueryAsync(model); } catch { return View("Error", new ErrorViewModel { RequestId = "1" }); } return View(model); } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } private static SearchClient _searchClient; private static SearchIndexClient _indexClient; private static IConfigurationBuilder _builder; private static IConfigurationRoot _configuration; private void InitSearch() { // Create a configuration using appsettings.json _builder = new ConfigurationBuilder().AddJsonFile("appsettings.json"); _configuration = _builder.Build(); // Read the values from appsettings.json string searchServiceUri = _configuration["SearchServiceUri"]; string queryApiKey = _configuration["SearchServiceQueryApiKey"]; // Create a service and index client. _indexClient = new SearchIndexClient(new Uri(searchServiceUri), new AzureKeyCredential(queryApiKey)); _searchClient = _indexClient.GetSearchClient("hotels-sample-index"); } private async Task<ActionResult> RunQueryAsync(SearchData model) { InitSearch(); var options = new SearchOptions() { IncludeTotalCount = true }; // Enter Hotel property names to specify which fields are returned. // If Select is empty, all "retrievable" fields are returned. options.Select.Add("HotelName"); options.Select.Add("Category"); options.Select.Add("Rating"); options.Select.Add("Tags"); options.Select.Add("Address/City"); options.Select.Add("Address/StateProvince"); options.Select.Add("Description"); // For efficiency, the search call should be asynchronous, so use SearchAsync rather than Search. model.resultList = await _searchClient.SearchAsync<Hotel>(model.searchText, options).ConfigureAwait(false); // Display the results. return View("Index", model); } public IActionResult Privacy() { return View(); } } }
Mengubah tampilan
Di Penjelajah solusi di bawah Beranda Tampilan>, buka .
index.cshtml
Ganti default dengan konten berikut:
@model HotelDemoApp.Models.SearchData; @{ ViewData["Title"] = "Index"; } <div> <h2>Search for Hotels</h2> <p>Use this demo app to test server-side sorting and filtering. Modify the RunQueryAsync method to change the operation. The app uses the default search configuration (simple search syntax, with searchMode=Any).</p> <form asp-controller="Home" asp-action="Index"> <p> <input type="text" name="searchText" /> <input type="submit" value="Search" /> </p> </form> </div> <div> @using (Html.BeginForm("Index", "Home", FormMethod.Post)) { @if (Model != null) { // Show the result count. <p>@Model.resultList.TotalCount Results</p> // Get search results. var results = Model.resultList.GetResults().ToList(); { <table class="table"> <thead> <tr> <th>Name</th> <th>Category</th> <th>Rating</th> <th>Tags</th> <th>City</th> <th>State</th> <th>Description</th> </tr> </thead> <tbody> @foreach (var d in results) { <tr> <td>@d.Document.HotelName</td> <td>@d.Document.Category</td> <td>@d.Document.Rating</td> <td>@d.Document.Tags[0]</td> <td>@d.Document.Address.City</td> <td>@d.Document.Address.StateProvince</td> <td>@d.Document.Description</td> </tr> } </tbody> </table> } } } </div>
Jalankan sampel
Tekan F5 untuk mengkompilasi dan menjalankan proyek. Aplikasi ini berjalan di host lokal dan terbuka di browser default Anda.
Pilih Cari untuk mengembalikan semua hasil.
Kode ini menggunakan konfigurasi pencarian default, mendukung sintaksis sederhana dan
searchMode=Any
. Anda dapat memasukkan kata kunci, menambah dengan operator Boolean, atau menjalankan pencarian awalan (pool*
).
Di beberapa bagian berikutnya, ubah metode RunQueryAsync di HomeController
untuk menambahkan filter dan pengurutan.
Memfilter hasil
Atribut bidang indeks menentukan bidang mana yang dapat dicari, dapat difilter, dapat diurutkan, dapat difaset, dan dapat diambil. Di indeks sampel hotel, bidang yang dapat difilter termasuk Kategori, Alamat/Kota, dan Alamat/StateProvince. Contoh ini menambahkan ekspresi $Filter pada Kategori.
Filter selalu dijalankan terlebih dahulu, diikuti oleh kueri dengan asumsi kueri ditentukan.
HomeController
Buka dan temukan metode RunQueryAsync. Tambahkan Filter kevar options = new SearchOptions()
:private async Task<ActionResult> RunQueryAsync(SearchData model) { InitSearch(); var options = new SearchOptions() { IncludeTotalCount = true, Filter = "search.in(Category,'Budget,Suite')" }; options.Select.Add("HotelName"); options.Select.Add("Category"); options.Select.Add("Rating"); options.Select.Add("Tags"); options.Select.Add("Address/City"); options.Select.Add("Address/StateProvince"); options.Select.Add("Description"); model.resultList = await _searchClient.SearchAsync<Hotel>(model.searchText, options).ConfigureAwait(false); return View("Index", model); }
Jalankan aplikasi lagi.
Pilih Cari untuk menjalankan kueri kosong. Filter mengembalikan 18 dokumen alih-alih 50 asli.
Untuk informasi selengkapnya tentang ekspresi filter, lihat Filter di Azure AI Search dan sintaks $filter OData di Azure AI Search.
Urukan hasil
Di indeks sampel hotel, bidang yang dapat diurutkan termasuk Peringkat dan LastRenovated. Contoh ini menambahkan ekspresi $OrderBy ke bidang Peringkat.
HomeController
Buka dan ganti metode RunQueryAsync dengan versi berikut:private async Task<ActionResult> RunQueryAsync(SearchData model) { InitSearch(); var options = new SearchOptions() { IncludeTotalCount = true, }; options.OrderBy.Add("Rating desc"); options.Select.Add("HotelName"); options.Select.Add("Category"); options.Select.Add("Rating"); options.Select.Add("Tags"); options.Select.Add("Address/City"); options.Select.Add("Address/StateProvince"); options.Select.Add("Description"); model.resultList = await _searchClient.SearchAsync<Hotel>(model.searchText, options).ConfigureAwait(false); return View("Index", model); }
Jalankan aplikasi lagi. Hasil diurutkan menurut Peringkat dalam urutan turun.
Untuk informasi selengkapnya tentang pengurutan, lihat sintaks $orderby OData di Azure AI Search.
Langkah berikutnya
Dalam tutorial ini, Anda membuat proyek ASP.NET Core (MVC) yang tersambung ke layanan pencarian dan disebut API Pencarian untuk pemfilteran dan pengurutan sisi server.
Jika Anda ingin menjelajahi kode sisi klien yang merespons tindakan pengguna, pertimbangkan untuk menambahkan templat React ke solusi Anda: