Keresési alkalmazás létrehozása a ASP.NET Core-ban
Ebben az oktatóanyagban hozzon létre egy alapszintű ASP.NET Core (Model-View-Controller) alkalmazást, amely a localhostban fut, és csatlakozik a keresési szolgáltatás hotels-sample-indexéhez. Az oktatóanyag segítségével megtanulhatja a következőket:
- Alapszintű keresési oldal létrehozása
- Szűrés eredményei
- Az eredmények rendezése
Ez az oktatóanyag a keresési API-kon keresztül meghívott kiszolgálóoldali műveletekre helyezi a hangsúlyt. Bár az ügyféloldali szkriptekben gyakran történik rendezés és szűrés, a keresési felület tervezésekor több lehetőséget is kínál a műveletek kiszolgálóra való meghívása.
Az oktatóanyag mintakódja a GitHub azure-search-dotnet-samples adattárában található.
Előfeltételek
- Visual Studio
- Azure.Search.Documents NuGet-csomag
- Azure AI Search, bármely szint, de nyilvános hálózati hozzáféréssel kell rendelkeznie.
- Szállodai minták indexe
Az Adatok importálása varázslóval létrehozhatja a hotels-sample-indexet a keresési szolgáltatásban. Vagy módosítsa az index nevét a HomeController.cs
fájlban.
A projekt létrehozása
Indítsa el a Visual Studiót, és válassza az Új projekt létrehozása lehetőséget.
Válassza ASP.NET Core Web App (Model-View-Controller) lehetőséget, majd válassza a Tovább gombot.
Adjon meg egy projektnevet, majd válassza a Tovább gombot.
A következő lapon válassza a .NET 6.0 vagy a .NET 7.0 vagy a .NET 8.0 lehetőséget.
Ellenőrizze, hogy nincs-e bejelölve a felső szintű utasítások használata.
Válassza a Létrehozás lehetőséget.
NuGet-csomagok hozzáadása
Az Eszközök lapon válassza a MegoldásHoz tartozó NuGet-Csomagkezelő> Manage NuGet-csomagokat.
Keresse meg
Azure.Search.Documents
és telepítse a legújabb stabil verziót.Keresse meg és telepítse a
Microsoft.Spatial
csomagot. A mintaindex tartalmaz egy GeographyPoint-adattípust. A csomag telepítése elkerüli a futásidejű hibákat. Ha nem szeretné telepíteni a csomagot, távolítsa el a "Hely" mezőt a Hotels osztályból. Ez a mező nem használatos ebben az oktatóanyagban.
Szolgáltatásadatok hozzáadása
A kapcsolathoz az alkalmazás egy lekérdezési API-kulcsot jelenít meg a teljes keresési URL-címhez. Mindkettő meg van adva a appsettings.json
fájlban.
Módosítsa appsettings.json
a keresési szolgáltatás és a lekérdezési API-kulcs megadásához.
{
"SearchServiceUri": "<YOUR-SEARCH-SERVICE-URL>",
"SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-QUERY-API-KEY>"
}
A szolgáltatás URL-címét és API-kulcsát az Azure Portalról szerezheti be. Mivel ez a kód egy indexet kérdez le, és nem hoz létre egyet, rendszergazdai kulcs helyett lekérdezési kulcsot is használhat.
Mindenképpen adja meg azt a keresési szolgáltatást, amely a hotels-sample-indexet tartalmazza.
Modellek hozzáadása
Ebben a lépésben olyan modelleket hozhat létre, amelyek a hotels-sample-index sémáját képviselik.
A Megoldáskezelőben válassza a jobb gombbal a Modellek lehetőséget, és adjon hozzá egy "Hotel" nevű új osztályt a következő kódhoz:
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; } } }
Adjon hozzá egy "Address" nevű osztályt, és cserélje le a következő kódra:
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; } } }
Adjon hozzá egy "Szobák" nevű osztályt, és cserélje le a következő kódra:
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; } } }
Adjon hozzá egy "SearchData" nevű osztályt, és cserélje le a következő kódra:
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; } }
A vezérlő módosítása
Ebben az oktatóanyagban módosítsa az alapértelmezett HomeController
beállítást úgy, hogy a keresési szolgáltatáson végrehajtott metódusokat tartalmazza.
A Megoldáskezelő Modellek csoportjában nyissa meg a elemet
HomeController
.Cserélje le az alapértelmezett értéket a következő tartalomra:
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(); } } }
A nézet módosítása
Nyissa meg
index.cshtml
a Megoldáskezelőben a Nézetek>kezdőlapja alatt.Cserélje le az alapértelmezett értéket a következő tartalomra:
@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>
Minta futtatása
A projekt fordításához és futtatásához nyomja le az F5 billentyűt. Az alkalmazás helyi gazdagépen fut, és az alapértelmezett böngészőben nyílik meg.
Válassza a Keresés lehetőséget az összes találat visszaadásához.
Ez a kód az alapértelmezett keresési konfigurációt használja, amely támogatja az egyszerű szintaxist és
searchMode=Any
a . Megadhat kulcsszavakat, bővíthet logikai operátorokkal, vagy futtathat előtagkeresést (pool*
).
A következő szakaszokban módosítsa a RunQueryAsync metódust a HomeController
szűrők és rendezés hozzáadásához.
Szűrés eredményei
Az indexmező attribútumai határozzák meg, hogy mely mezők kereshetők, szűrhetők, rendezhetők, táblázatosak és lekérdezhetők. A szállodák mintaindexében a szűrhető mezők közé tartozik a Kategória, a Cím/Város és a Cím/StateProvince. Ez a példa egy $Filter kifejezést ad hozzá a Kategóriához.
A szűrő mindig először fut, majd egy lekérdezés, feltéve, hogy van megadva.
Nyissa meg a
HomeController
RunQueryAsync metódust, és keresse meg. Szűrő hozzáadása a következőhözvar 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); }
Futtassa az alkalmazást.
Üres lekérdezés futtatásához válassza a Keresés lehetőséget. A szűrő az eredeti 50 helyett 18 dokumentumot ad vissza.
További információ a szűrőkifejezésekről: Szűrők az Azure AI Searchben és OData $filter szintaxis az Azure AI Searchben.
Az eredmények rendezése
A szállodák mintaindexében a rendezhető mezők közé tartozik a Minősítés és a LastRenovated. Ez a példa egy $OrderBy kifejezést ad hozzá a Minősítés mezőhöz.
Nyissa meg és cserélje le a
HomeController
RunQueryAsync metódust a következő verzióra: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); }
Futtassa az alkalmazást. Az eredmények besorolása csökkenő sorrendben van rendezve.
A rendezéssel kapcsolatos további információkért lásd az OData $orderby szintaxisát az Azure AI Searchben.
Következő lépések
Ebben az oktatóanyagban létrehozott egy ASP.NET Core (MVC) projektet, amely egy keresési szolgáltatáshoz csatlakozott, és a kiszolgálóoldali szűréshez és rendezéshez keresési API-knak nevezett.
Ha meg szeretné vizsgálni a felhasználói műveletekre reagáló ügyféloldali kódot, fontolja meg egy React-sablon hozzáadását a megoldáshoz: