ASP.NET Core'da arama uygulaması oluşturma
Bu öğreticide, localhost'ta çalışan ve arama hizmetinizdeki hotels-sample-index öğesine bağlanan temel bir ASP.NET Core (Model-View-Controller) uygulaması oluşturun. Bu öğreticide aşağıdakilerin nasıl yapılacağını öğreneceksiniz:
- Temel arama sayfası oluşturma
- Sonuçları filtrele
- Sonuçları sıralama
Bu öğretici, odağı Arama API'leri aracılığıyla çağrılan sunucu tarafı işlemlerine getirir. İstemci tarafı betiğinde sıralamak ve filtrelemek yaygın olsa da, bu işlemlerin sunucuda nasıl çağrılılacağını bilmek, arama deneyimini tasarlarken size daha fazla seçenek sunar.
Bu öğreticinin örnek kodu GitHub'daki azure-search-dotnet-samples deposunda bulunabilir.
Önkoşullar
- Visual Studio
- Azure.Search.Documents NuGet paketi
- Azure AI Search, herhangi bir katman, ancak genel ağ erişimine sahip olmalıdır.
- Otel örnekleri dizini
Arama hizmetinizde hotels-sample-index oluşturmak için Verileri içeri aktarma sihirbazında ilerleyin. Alternatif olarak, dosyadaki dizin adını da HomeController.cs
değiştirebilirsiniz.
Proje oluşturma
Visual Studio'yu başlatın ve Yeni proje oluştur'u seçin.
ASP.NET Core Web App (Model-View-Controller) öğesini ve ardından İleri'yi seçin.
Bir proje adı girin ve İleri'yi seçin.
Sonraki sayfada .NET 6.0 veya .NET 7.0 veya .NET 8.0'ı seçin.
Üst düzey deyimleri kullanma seçeneğinin işaretli olmadığını doğrulayın.
Oluştur'u belirleyin.
NuGet paketlerini ekleme
Araçlar'da Çözüm için NuGet Paket Yöneticisi> Yönetim NuGet Paketlerini Yönet'i seçin.
En son kararlı sürümü bulun
Azure.Search.Documents
ve yükleyin.Paketi bulun ve yükleyin
Microsoft.Spatial
. Örnek dizin bir GeographyPoint veri türü içerir. Bu paketin yüklenmesi çalışma zamanı hatalarını önler. Alternatif olarak, paketi yüklemek istemiyorsanız Hotels sınıfından "Konum" alanını kaldırın. Bu alan bu öğreticide kullanılmaz.
Hizmet bilgileri ekleme
Bağlantı için uygulama, tam arama URL'nize bir sorgu API'si anahtarı sunar. Her ikisi de dosyada appsettings.json
belirtilir.
Arama hizmetinizi ve sorgu API anahtarınızı belirtmek için değiştirinappsettings.json
.
{
"SearchServiceUri": "<YOUR-SEARCH-SERVICE-URL>",
"SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-QUERY-API-KEY>"
}
Hizmet URL'sini ve API anahtarını Azure portalından alabilirsiniz. Bu kod bir dizini sorguladığı ve oluşturmadığı için yönetici anahtarı yerine sorgu anahtarı kullanabilirsiniz.
hotels-sample-index içeren arama hizmetini belirttiğinizden emin olun.
Model ekleme
Bu adımda hotels-sample-index şemasını temsil eden modeller oluşturun.
Çözüm gezgininde Modeller'i sağ seçin ve aşağıdaki kod için "Hotel" adlı yeni bir sınıf ekleyin:
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; } } }
"Address" adlı bir sınıf ekleyin ve bunu aşağıdaki kodla değiştirin:
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; } } }
"Rooms" adlı bir sınıf ekleyin ve bunu aşağıdaki kodla değiştirin:
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; } } }
"SearchData" adlı bir sınıf ekleyin ve bunu aşağıdaki kodla değiştirin:
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; } }
Denetleyiciyi değiştirme
Bu öğreticide, arama hizmetinizde yürütülen yöntemleri içeren varsayılan HomeController
değeri değiştirin.
Çözüm gezgini'nde Modeller'in altında öğesini açın
HomeController
.Varsayılan değeri aşağıdaki içerikle değiştirin:
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(); } } }
Görünümü değiştirme
Çözüm gezgininde, Görünümler>Giriş'in altında öğesini açın.
index.cshtml
Varsayılan değeri aşağıdaki içerikle değiştirin:
@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>
Örneği çalıştırma
Projeyi derlemek ve çalıştırmak için F5 tuşuna basın. Uygulama yerel ana bilgisayarda çalışır ve varsayılan tarayıcınızda açılır.
Tüm sonuçları döndürmek için Ara'yı seçin.
Bu kod, ve basit söz dizimini
searchMode=Any
destekleyen varsayılan arama yapılandırmasını kullanır. Anahtar sözcükler girebilir, Boole işleçleriyle genişletebilir veya bir ön ek araması (pool*
) çalıştırabilirsiniz.
Sonraki birkaç bölümde, filtre ve sıralama eklemek için içindeki HomeController
RunQueryAsync yöntemini değiştirin.
Sonuçları filtrele
Dizin alanı öznitelikleri hangi alanların aranabilir, filtrelenebilir, sıralanabilir, modellenebilir ve alınabilir olduğunu belirler. hotels-sample-index içinde filtrelenebilir alanlar Kategori, Adres/Şehir ve Adres/StateProvince'tır. Bu örnek, Category'ye bir $Filter ifadesi ekler.
Her zaman önce bir filtre yürütülür, ardından bir sorgu belirtilir.
HomeController
öğesini açın ve RunQueryAsync yöntemini bulun. Içinevar options = new SearchOptions()
Filtre Ekle: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); }
Uygulamayı çalıştırın.
Boş bir sorgu çalıştırmak için Ara'yı seçin. Filtre, özgün 50 yerine 18 belge döndürür.
Filtre ifadeleri hakkında daha fazla bilgi için bkz. Azure AI Search'teki filtreler ve Azure AI Search'te OData $filter söz dizimi.
Sonuçları sıralama
Hotels-sample-index içinde sıralanabilir alanlar Derecelendirme ve LastRenovated alanlarını içerir. Bu örnek Derecelendirme alanına bir $OrderBy ifadesi ekler.
HomeController
ve runQueryAsync yöntemini aşağıdaki sürümle değiştirin: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); }
Uygulamayı çalıştırın. Sonuçlar Derecelendirmeye göre azalan düzende sıralanır.
Sıralama hakkında daha fazla bilgi için bkz . Azure AI Search'te OData $orderby söz dizimi.
Sonraki adımlar
Bu öğreticide, bir arama hizmetine bağlı olan ve sunucu tarafı filtreleme ve sıralama için Arama API'leri olarak adlandırılan bir ASP.NET Core (MVC) projesi oluşturdunuz.
Kullanıcı eylemlerine yanıt veren istemci tarafı kodunu keşfetmek istiyorsanız çözümünüze bir React şablonu eklemeyi göz önünde bulundurun: