Självstudie: Skapa din första sökapp i Azure Cognitive Search med hjälp av .NET SDK
Den här självstudien visar hur du skapar en webbapp som frågar efter och returnerar resultat från ett sökindex med hjälp av Azure Cognitive Search och Visual Studio.
I den här självstudien får du lära dig att:
- Konfigurera en utvecklingsmiljö
- Modellera datastrukturer
- Skapa en webbsida för att samla in frågeindata och visa resultat
- Definiera en sökmetod
- Testa appen
Du får också lära dig hur enkelt ett söksamtal är. Nyckelinstruktionerna i koden kapslas in i följande rader:
var options = new SearchOptions()
{
// The Select option specifies fields for the result set
options.Select.Add("HotelName");
options.Select.Add("Description");
};
var searchResult = await _searchClient.SearchAsync<Hotel>(model.searchText, options).ConfigureAwait(false);
model.resultList = searchResult.Value.GetResults().ToList();
Bara ett anrop frågar sökindexet och returnerar resultat.
Översikt
I den här självstudien används hotels-sample-index, som du snabbt kan skapa i din egen söktjänst genom att gå igenom snabbstarten Importera data. Indexet innehåller fiktiva hotelldata som är tillgängliga som en inbyggd datakälla i varje söktjänst.
Den första lektionen i den här självstudien skapar en grundläggande frågestruktur och en söksida, som du kommer att förbättra under efterföljande lektioner med sidindelning, fasetter och en upplevelse av typen framåt.
En färdig version av koden finns i följande projekt:
Förutsättningar
Exempelindex (hotels-sample-index), som finns i söktjänsten.
Installera och köra projektet från GitHub
Om du vill gå vidare till en fungerande app följer du stegen nedan för att ladda ned och köra den färdiga koden.
Leta upp exemplet på GitHub: Skapa den första appen.
I rotmappen väljer du Kod följt av Klona eller Ladda ned ZIP för att göra din privata lokala kopia av projektet.
Använd Visual Studio, navigera till och öppna lösningen för den grundläggande söksidan ("1-basic-search-page") och välj Starta utan felsökning (eller tryck på F5) för att skapa och köra programmet.
Det här är ett hotellindex, så skriv in några ord som du kan använda för att söka efter hotell (till exempel "wifi", "view", "bar", "parking"). Granska resultatet.
De viktigaste komponenterna för mer avancerade sökningar ingår i den här appen. Om du inte har använt sökutveckling tidigare kan du återskapa den här appen steg för steg för att lära dig arbetsflödet. I följande avsnitt visas hur du gör.
Konfigurera en utvecklingsmiljö
Börja med ett Visual Studio-projekt för att skapa det här projektet från grunden och därmed förstärka begreppen i Azure Cognitive Search.
I Visual Studio väljer du Nytt>projekt och sedan ASP.NET Core Webbapp (Model-View-Controller).
Ge projektet ett namn som "FirstSearchApp" och ange platsen. Välj Nästa.
Acceptera standardinställningarna för målramverk, autentiseringstyp och HTTPS. Välj Skapa.
Installera klientbiblioteket. I Verktyg>NuGet Package Manager>Hantera NuGet-paket för lösningen... väljer du Bläddra och söker sedan efter "azure.search.documents". Installera Azure.Search.Documents (version 11 eller senare) och acceptera licensavtalen och beroendena.
Initiera Azure Cognitive Search
I det här steget anger du slutpunkten och åtkomstnyckeln för att ansluta till söktjänsten som tillhandahåller hotellens exempelindex.
Öppna appsettings.json och ersätt standardraderna med söktjänstens URL (i formatet
https://<service-name>.search.windows.net
) och en administratörs- eller fråge-API-nyckel för din söktjänst. Eftersom du inte behöver skapa eller uppdatera ett index kan du använda frågenyckeln för den här självstudien.{ "SearchServiceUri": "<YOUR-SEARCH-SERVICE-URI>", "SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-API-KEY>" }
I Solution Explorer väljer du filen och i Egenskaper ändrar du inställningen Kopiera till utdatakatalog till Kopiera om nyare.
Modellera datastrukturer
Modeller (C#-klasser) används för att kommunicera data mellan klienten (vyn), servern (kontrollanten) och även Azure-molnet med hjälp av arkitekturen MVC (modell, vy, kontrollant). Dessa modeller återspeglar vanligtvis strukturen för de data som används.
I det här steget ska du modellera datastrukturerna för sökindexet samt söksträngen som används i kommunikation mellan vy och kontrollant. I hotellindexet har varje hotell många rum och varje hotell har en adress i flera delar. Sammantaget är en fullständig representation av ett hotell en hierarkisk och kapslad datastruktur. Du behöver tre klasser för att skapa varje komponent.
Uppsättningen av hotell-, adress- och rumsklasser kallas komplexa typer, ett viktigt inslag i Azure Cognitive Search. Komplexa typer kan vara många nivåer djup i klasser och underklasser och göra det möjligt att representera mycket mer komplexa datastrukturer än att använda enkla typer (en klass som endast innehåller primitiva medlemmar).
I Solution Explorer högerklickar du på Modeller>Lägg till>nytt objekt.
Välj Klass och ge objektet namnet Hotel.cs. Ersätt allt innehåll i Hotel.cs med följande kod. Observera klassens adress - och rumsmedlemmar . Dessa fält är själva klasserna, så du behöver modeller för dem också.
using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; using Microsoft.Spatial; using System; using System.Text.Json.Serialization; namespace FirstAzureSearchApp.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 Room[] Rooms { get; set; } } }
Upprepa samma process för att skapa en modell för klassen Address och namnge filen Address.cs. Ersätt innehållet med följande.
using Azure.Search.Documents.Indexes; namespace FirstAzureSearchApp.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; } } }
Och följ samma process för att skapa klassen Room och namnge filen Room.cs.
using Azure.Search.Documents.Indexes; using Azure.Search.Documents.Indexes.Models; using System.Text.Json.Serialization; namespace FirstAzureSearchApp.Models { public partial class Room { [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; } } }
Den sista modellen som du skapar i den här självstudien är en klass med namnet SearchData och representerar användarens indata (searchText) och sökningens utdata (resultList). Utdatatypen är kritisk, SearchResults<Hotel>, eftersom den här typen exakt matchar resultatet från sökningen, och du måste skicka den här referensen till vyn. Ersätt standardmallen med följande kod.
using Azure.Search.Documents.Models; namespace FirstAzureSearchApp.Models { public class SearchData { // The text to search for. public string searchText { get; set; } // The list of results. public SearchResults<Hotel> resultList; } }
Skapa en webbsida
Projektmallar levereras med ett antal klientvyer som finns i mappen Vyer . De exakta vyerna beror på vilken version av Core .NET du använder (3.1 används i det här exemplet). I den här självstudien ändrar du Index.cshtml så att elementen på en söksida inkluderas.
Ta bort innehållet i Index.cshtml i sin helhet och återskapa filen i följande steg.
I självstudien används två små bilder i vyn: en Azure-logotyp och en förstoringsikon för sökning (azure-logo.png och search.png). Kopiera över bilderna från GitHub-projektet till mappen wwwroot/images i projektet.
Den första raden i Index.cshtml ska referera till modellen som används för att kommunicera data mellan klienten (vyn) och servern (kontrollanten), som är Den SearchData-modell som skapades tidigare. Lägg till den här raden i filen Index.cshtml.
@model FirstAzureSearchApp.Models.SearchData
Det är standard att ange en rubrik för vyn, så nästa rader bör vara:
@{ ViewData["Title"] = "Home Page"; }
Efter rubriken anger du en referens till en HTML-formatmall som du snart ska skapa.
<head> <link rel="stylesheet" href="~/css/hotels.css" /> </head>
Brödtexten i vyn hanterar två användningsfall. Först måste den ange en tom sida vid första användning, innan någon söktext anges. För det andra måste den hantera resultat, förutom söktextrutan, för upprepade frågor.
För att hantera båda fallen måste du kontrollera om modellen som tillhandahålls till vyn är null. En null-modell anger det första användningsfallet (den första körningen av appen). Lägg till följande i filen Index.cshtml och läs igenom kommentarerna.
<body> <h1 class="sampleTitle"> <img src="~/images/azure-logo.png" width="80" /> Hotels Search </h1> @using (Html.BeginForm("Index", "Home", FormMethod.Post)) { // Display the search text box, with the search icon to the right of it. <div class="searchBoxForm"> @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox" }) <input class="searchBoxSubmit" type="submit" value=""> </div> @if (Model != null) { // Show the result count. <p class="sampleText"> @Model.resultList.TotalCount Results </p> var results = Model.resultList.GetResults().ToList(); @for (var i = 0; i < results.Count; i++) { // Display the hotel name and description. @Html.TextAreaFor(m => results[i].Document.HotelName, new { @class = "box1" }) @Html.TextArea($"desc{i}", results[i].Document.Description, new { @class = "box2" }) } } } </body>
Lägg till formatmallen. I Visual Studio går du till Arkiv>Ny>fil och väljer Formatmall (med Allmänt markerat).
Ersätt standardkoden med följande. Vi kommer inte att gå in i den här filen mer detaljerat, formaten är standard-HTML.
textarea.box1 { width: 648px; height: 30px; border: none; background-color: azure; font-size: 14pt; color: blue; padding-left: 5px; } textarea.box2 { width: 648px; height: 100px; border: none; background-color: azure; font-size: 12pt; padding-left: 5px; margin-bottom: 24px; } .sampleTitle { font: 32px/normal 'Segoe UI Light',Arial,Helvetica,Sans-Serif; margin: 20px 0; font-size: 32px; text-align: left; } .sampleText { font: 16px/bold 'Segoe UI Light',Arial,Helvetica,Sans-Serif; margin: 20px 0; font-size: 14px; text-align: left; height: 30px; } .searchBoxForm { width: 648px; box-shadow: 0 0 0 1px rgba(0,0,0,.1), 0 2px 4px 0 rgba(0,0,0,.16); background-color: #fff; display: inline-block; border-collapse: collapse; border-spacing: 0; list-style: none; color: #666; } .searchBox { width: 568px; font-size: 16px; margin: 5px 0 1px 20px; padding: 0 10px 0 0; border: 0; max-height: 30px; outline: none; box-sizing: content-box; height: 35px; vertical-align: top; } .searchBoxSubmit { background-color: #fff; border-color: #fff; background-image: url(/images/search.png); background-repeat: no-repeat; height: 20px; width: 20px; text-indent: -99em; border-width: 0; border-style: solid; margin: 10px; outline: 0; }
Spara formatmallsfilen som hotels.css i mappen wwwroot/css tillsammans med standardfilen site.css.
Det fullbordar vår åsikt. Nu slutförs både modellerna och vyerna. Endast kontrollanten är kvar för att knyta ihop allt.
Definiera metoder
I det här steget ändrar du till innehållet i Startkontrollanten.
Öppna filen HomeController.cs och ersätt using-instruktionerna med följande.
using Azure; using Azure.Search.Documents; using Azure.Search.Documents.Indexes; using FirstAzureSearchApp.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using System; using System.Diagnostics; using System.Linq; using System.Threading.Tasks;
Lägg till indexmetoder
I en MVC-app är metoden Index() en standardåtgärdsmetod för alla kontrollanter. Html-indexsidan öppnas. Standardmetoden, som inte tar några parametrar, används i den här självstudien för användningsfallet för programstart: återgivning av en tom söksida.
I det här avsnittet utökar vi metoden för att stödja ett andra användningsfall: återgivning av sidan när en användare har angett söktext. För att stödja det här fallet utökas indexmetoden för att ta en modell som en parameter.
Lägg till följande metod efter standardmetoden Index().
[HttpPost] public async Task<ActionResult> Index(SearchData model) { try { // Ensure the search string is valid. if (model.searchText == null) { model.searchText = ""; } // Make the Azure Cognitive Search call. await RunQueryAsync(model); } catch { return View("Error", new ErrorViewModel { RequestId = "1" }); } return View(model); }
Observera metodens asynkrona deklaration och await-anropet till RunQueryAsync. Dessa nyckelord tar hand om asynkrona anrop och undviker därmed blockering av trådar på servern.
Catch-blocket använder standardfelmodellen som skapades.
Observera felhantering och andra standardvyer och metoder
Beroende på vilken version av .NET Core du använder skapas en något annorlunda uppsättning standardvyer. För .NET Core 3.1 är standardvyerna Index, Sekretess och Fel. Du kan visa dessa standardsidor när du kör appen och undersöka hur de hanteras i kontrollanten.
Du kommer att testa felvyn senare i den här självstudien.
I GitHub-exemplet tas oanvända vyer och deras associerade åtgärder bort.
Lägg till metoden RunQueryAsync
Anropet Azure Cognitive Search kapslas in i vår RunQueryAsync-metod.
Lägg först till några statiska variabler för att konfigurera Azure-tjänsten och ett anrop för att initiera dem.
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"); }
Lägg nu till själva Metoden RunQueryAsync .
private async Task<ActionResult> RunQueryAsync(SearchData model) { InitSearch(); var options = new SearchOptions() { IncludeTotalCount = true }; // Enter Hotel property names into this list so only these values will be returned. // If Select is empty, all values will be returned, which can be inefficient. options.Select.Add("HotelName"); 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); }
I den här metoden kontrollerar du först att azure-konfigurationen har initierats och anger sedan några sökalternativ. Alternativet Välj anger vilka fält som ska returneras i resultat och matchar därmed egenskapsnamnen i hotellklassen . Om du utelämnar Markera returneras alla odefinierade fält, vilket kan vara ineffektivt om du bara är intresserad av en delmängd av alla möjliga fält.
Det asynkrona anropet för att söka formulerar begäran (modellerad som searchText) och svaret (modellerat som searchResult). Om du felsöker den här koden är klassen SearchResult en bra kandidat för att ange en brytpunkt om du behöver undersöka innehållet i model.resultList. Du bör upptäcka att det är intuitivt, att bara tillhandahålla de data som du bad om, och inte mycket annat.
Testa appen
Nu ska vi kontrollera om appen körs korrekt.
Välj Felsöka>start utan att felsöka eller tryck på F5. Om appen körs som förväntat bör du få den första indexvyn.
Ange en frågesträng, till exempel "beach" (eller någon text som kommer att tänka på), och klicka på sökikonen för att skicka begäran.
Försök att ange "fem stjärnor". Observera att den här frågan inte returnerar några resultat. En mer sofistikerad sökning skulle behandla "femstjärnig" som en synonym till "lyx" och returnera dessa resultat. Stöd för synonymer är tillgängligt i Azure Cognitive Search, men tas inte upp i den här självstudieserien.
Försök att ange "hot" som söktext. Det returnerar inte poster med ordet "hotell" i dem. Sökningen lokaliserar bara hela ord, även om några få resultat returneras.
Prova med andra ord: "pool", "sunshine", "view" och vad som helst. Du kommer att se Azure Cognitive Search arbeta på sin enklaste, men fortfarande övertygande nivå.
Testa gränsvillkor och fel
Det är viktigt att kontrollera att våra felhanteringsfunktioner fungerar som de ska, även när saker och ting fungerar perfekt.
Efter {-anropet i indexmetoden anger du raden Throw new Exception(). Det här undantaget framtvingar ett fel när du söker efter text.
Kör appen, ange "bar" som söktext och klicka på sökikonen. Undantaget bör resultera i felvyn.
Viktigt
Det anses vara en säkerhetsrisk att returnera interna felnummer på felsidor. Om din app är avsedd för allmän användning följer du rekommenderade säkerhetsmetoder för vad som ska returneras när ett fel inträffar.
Ta bort Throw new Exception() när du är nöjd med att felhanteringen fungerar som den ska.
Lärdomar
Tänk på följande från det här projektet:
- Ett Azure Cognitive Search-anrop är koncist och det är enkelt att tolka resultaten.
- Asynkrona anrop lägger till en liten mängd komplexitet till kontrollanten, men det är bästa praxis som förbättrar prestandan.
- Den här appen utförde en enkel textsökning som definieras av vad som konfigurerats i searchOptions. Den här klassen kan dock fyllas med många medlemmar som lägger till sofistikering i en sökning. Med lite mer arbete kan du göra den här appen betydligt kraftfullare.
Nästa steg
För att förbättra användarupplevelsen lägger du till fler funktioner, särskilt sidindelning (antingen med sidnummer eller oändlig rullning) och komplettera automatiskt/förslag. Du kan också överväga andra sökalternativ (till exempel geografiska sökningar på hotell inom en angiven radie från en viss punkt) och sökresultatordning.
De här nästa stegen beskrivs i de återstående självstudierna. Vi börjar med sidindelning.