Vytvoření vyhledávací aplikace v ASP.NET Core
V tomto kurzu vytvořte základní aplikaci ASP.NET Core (Model-View-Controller), která běží v místním hostiteli a připojuje se k indexu hotels-sample-index ve vyhledávací službě. V tomto kurzu se naučíte:
- Vytvoření základní vyhledávací stránky
- Filtrování výsledků
- Řazení výsledků
V tomto kurzu se zaměříme na operace na straně serveru volané prostřednictvím rozhraní API vyhledávání. I když je běžné řadit a filtrovat ve skriptu na straně klienta, znalost toho, jak tyto operace vyvolat na serveru, nabízí při návrhu vyhledávacího prostředí více možností.
Vzorový kód pro tento kurz najdete v úložišti azure-search-dotnet-samples na GitHubu.
Požadavky
- Visual Studio
- Balíček NuGet Azure.Search.Documents
- Azure AI Search, libovolná úroveň, ale musí mít přístup k veřejné síti.
- Index ukázek hotelů
Projděte si průvodce importem dat a vytvořte ve vyhledávací službě index hotels-sample-index. Nebo změňte název indexu HomeController.cs
v souboru.
Vytvoření projektu
Spusťte Visual Studio a vyberte Vytvořit nový projekt.
Vyberte ASP.NET Základní webová aplikace (Model-View-Controller) a pak vyberte Další.
Zadejte název projektu a pak vyberte Další.
Na další stránce vyberte .NET 6.0 nebo .NET 7.0 nebo .NET 8.0.
Ověřte, že není zaškrtnuto políčko Nepoužívat příkazy nejvyšší úrovně.
Vyberte Vytvořit.
Přidání balíčků NuGet
V nástrojích vyberte NuGet Správce balíčků> Nabídky NuGet pro řešení.
Azure.Search.Documents
Vyhledejte a nainstalujte nejnovější stabilní verzi.Vyhledejte a nainstalujte
Microsoft.Spatial
balíček. Ukázkový index obsahuje datový typ GeographyPoint. Instalace tohoto balíčku zabraňuje chybám za běhu. Pokud nechcete balíček nainstalovat, odeberte pole Umístění z třídy Hotely. Toto pole se v tomto kurzu nepoužívá.
Přidání informací o službě
Pro připojení aplikace zobrazí klíč rozhraní API dotazu na plně kvalifikovanou adresu URL vyhledávání. Oba jsou v souboru zadány appsettings.json
.
Upravte appsettings.json
zadání vyhledávací služby a klíče rozhraní API pro dotazy.
{
"SearchServiceUri": "<YOUR-SEARCH-SERVICE-URL>",
"SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-QUERY-API-KEY>"
}
Adresu URL služby a klíč rozhraní API můžete získat z webu Azure Portal. Vzhledem k tomu, že tento kód dotazuje index a nevytvořuje ho, můžete místo klíče správce použít klíč dotazu.
Nezapomeňte zadat vyhledávací službu, která má index hotels-sample-index.
Přidání modelů
V tomto kroku vytvořte modely, které představují schéma hotels-sample-index.
V Průzkumníku řešení vyberte pravým tlačítkem myši Modely a přidejte novou třídu s názvem "Hotel" pro následující kód:
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; } } }
Přidejte třídu s názvem Address a nahraďte ji následujícím kódem:
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; } } }
Přidejte třídu s názvem Rooms a nahraďte ji následujícím kódem:
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; } } }
Přidejte třídu s názvem SearchData a nahraďte ji následujícím kódem:
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; } }
Úprava kontroleru
V tomto kurzu upravte výchozí hodnotu HomeController
tak, aby obsahovala metody spouštěné ve vyhledávací službě.
V Průzkumníku řešení v části Modely otevřete
HomeController
.Nahraďte výchozí obsah následujícím obsahem:
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(); } } }
Úprava zobrazení
V Průzkumníku řešení v části Domovská stránka zobrazení>otevřete
index.cshtml
.Nahraďte výchozí obsah následujícím obsahem:
@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>
Spuštění ukázky
Stisknutím klávesy F5 projekt zkompilujte a spusťte. Aplikace běží na místním hostiteli a otevře se ve výchozím prohlížeči.
Výběrem možnosti Hledat vrátíte všechny výsledky.
Tento kód používá výchozí konfiguraci vyhledávání, která podporuje jednoduchou syntaxi a
searchMode=Any
. Můžete zadat klíčová slova, rozšířit o logické operátory nebo spustit vyhledávání předpon (pool*
).
V dalších několika částech upravte metodu RunQueryAsync v přidání HomeController
filtrů a řazení.
Filtrování výsledků
Atributy pole indexu určují, která pole jsou prohledávatelná, filtrovatelná, řaditelná, fasetová a načístelná. V indexu hotels-sample-index jsou filtrovatelná pole Kategorie, Adresa/Město a Address/StateProvince. Tento příklad přidá výraz $Filter v kategorii.
Filtr se vždy spustí jako první, po kterém následuje dotaz za předpokladu, že je zadaný.
Otevřete metodu
HomeController
RunQueryAsync a vyhledejte ji. Přidat filtr dovar 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); }
Aplikaci spusťte.
Výběrem možnosti Hledat spustíte prázdný dotaz. Filtr vrátí místo původního čísla 50 18 dokumentů.
Další informace o výrazech filtru najdete v tématu Filtry ve službě Azure AI Search a syntaxi $filter OData ve službě Azure AI Search.
Řazení výsledků
V indexu hotels-sample-index jsou seřazená pole Hodnocení a LastRenovated. Tento příklad přidá výraz $OrderBy do pole Hodnocení.
Otevřete a nahraďte metodu
HomeController
RunQueryAsync následující verzí: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); }
Aplikaci spusťte. Výsledky jsou seřazené podle hodnocení v sestupném pořadí.
Další informace o řazení najdete v tématu OData $orderby syntaxe ve službě Azure AI Search.
Další kroky
V tomto kurzu jste vytvořili projekt ASP.NET Core (MVC), který se připojil k vyhledávací službě a volal rozhraní API pro vyhledávání pro filtrování a řazení na straně serveru.
Pokud chcete prozkoumat kód na straně klienta, který reaguje na akce uživatelů, zvažte přidání šablony React do vašeho řešení: