Zelfstudie: Uw eerste zoek-app maken in Azure Cognitive Search met behulp van de .NET SDK
In deze zelfstudie leert u hoe u een web-app maakt die met behulp van Azure Cognitive Search en Visual Studio een query uitvoert en resultaten uit een zoekindex retourneert.
In deze zelfstudie leert u het volgende:
- Een ontwikkelomgeving instellen
- Gegevensstructuren modelleren
- Een webpagina maken om queryinvoer te verzamelen en resultaten weer te geven
- Een zoekmethode definiëren
- De app testen
U leert ook hoe eenvoudig een zoekopdracht is. De belangrijkste instructies in de code zijn ingekapseld in de volgende regels:
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();
Slechts één aanroep voert een query uit op de zoekindex en retourneert resultaten.
Overzicht
In deze zelfstudie wordt gebruikgemaakt van de hotels-sample-index, die u snel op uw eigen zoekservice kunt maken door de quickstart Gegevens importeren te doorlopen. De index bevat fictieve hotelgegevens, die beschikbaar zijn als een ingebouwde gegevensbron in elke zoekservice.
In de eerste les in deze zelfstudie maakt u een eenvoudige querystructuur en zoekpagina, die u in de volgende lessen gaat verbeteren met paging, facetten en een ervaring voor vooruittypen.
Een voltooide versie van de code vindt u in het volgende project:
Vereisten
Eenbestaande zoekservice maken of zoeken.
Voorbeeldindex (hotels-sample-index), gehost op uw zoekservice.
Het project installeren en uitvoeren vanuit GitHub
Als u naar een werkende app wilt springen, volgt u de onderstaande stappen om de voltooide code te downloaden en uit te voeren.
Zoek het voorbeeld op GitHub: Eerste app maken.
Selecteer Code in de hoofdmap, gevolgd door Zip-bestandklonen of downloaden om uw persoonlijke lokale kopie van het project te maken.
Ga met Visual Studio naar de oplossing voor de basiszoekpagina ('1-basic-search-page') en selecteer Starten zonder foutopsporing (of druk op F5) om het programma te bouwen en uit te voeren.
Dit is een hotelsindex, dus typ enkele woorden die u kunt gebruiken om te zoeken naar hotels (bijvoorbeeld 'wifi', 'view', 'bar', 'parking'). Bekijk de resultaten.
De essentiële onderdelen voor geavanceerdere zoekopdrachten zijn opgenomen in deze ene app. Als u geen kennis hebt van zoekontwikkeling, kunt u deze app stap voor stap opnieuw maken om de werkstroom te leren. In de volgende secties wordt uitgelegd hoe u dit kunt doen.
Een ontwikkelomgeving instellen
Als u dit project helemaal opnieuw wilt maken en zo de concepten van Azure Cognitive Search wilt versterken, begint u met een Visual Studio-project.
Selecteer in Visual Studio De optie Nieuw>projecten ASP.NET Core web-app (Model-View-Controller).
Geef het project een naam zoals 'FirstSearchApp' en stel de locatie in. Selecteer Next.
Accepteer de standaardwaarden voor het doelframework, verificatietype en HTTPS. Selecteer Maken.
Installeer de clientbibliotheek. Selecteer in Tools>NuGet Package Manager>Manage NuGet Packages for Solution...de optie Bladeren en zoek vervolgens naar 'azure.search.documents'. Installeer Azure.Search.Documents (versie 11 of hoger) en accepteer de licentieovereenkomsten en afhankelijkheden.
Azure Cognitive Search initialiseren
In deze stap stelt u het eindpunt en de toegangssleutel in om verbinding te maken met de zoekservice die de voorbeeldindex van hotels levert.
Open appsettings.json en vervang de standaardregels door de zoekservice-URL (in de indeling
https://<service-name>.search.windows.net
) en een beheerder- of query-API-sleutel van uw zoekservice. Omdat u geen index hoeft te maken of bij te werken, kunt u de querysleutel voor deze zelfstudie gebruiken.{ "SearchServiceUri": "<YOUR-SEARCH-SERVICE-URI>", "SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-API-KEY>" }
Selecteer het bestand in Solution Explorer en wijzig in Eigenschappen de instelling Kopiëren naar uitvoermap in Kopiëren indien nieuwer.
Gegevensstructuren modelleren
Modellen (C#-klassen) worden gebruikt om gegevens te communiceren tussen de client (de weergave), de server (de controller) en ook de Azure-cloud met behulp van de MVC-architectuur (model, view, controller). Deze modellen weerspiegelen doorgaans de structuur van de gegevens die worden geopend.
In deze stap gaat u de gegevensstructuren van de zoekindex modelleren, evenals de zoekreeks die wordt gebruikt in weergave-/controllercommunicatie. In de hotelsindex heeft elk hotel veel kamers en elk hotel heeft een meerdelig adres. De volledige weergave van een hotel is een hiërarchische en geneste gegevensstructuur. U hebt drie klassen nodig om elk onderdeel te maken.
De reeks hotel-, adres- en kamerklassen worden complexe typen genoemd, een belangrijk kenmerk van Azure Cognitive Search. Complexe typen kunnen bestaan uit een groot aantal klassen en subklassen, en veel complexere gegevensstructuren weergeven dan eenvoudige typen (een klasse met alleen primitieve leden).
Klik in Solution Explorer met de rechtermuisknop op Modellen>Nieuw itemtoevoegen>.
Selecteer Klasse en geef het item de naam Hotel.cs. Vervang alle inhoud van Hotel.cs door de volgende code. Let op de adres- en ruimteleden van de klasse. Deze velden zijn klassen zelf, dus u hebt ook modellen voor hen nodig.
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; } } }
Herhaal hetzelfde proces voor het maken van een model voor de klasse Address , waarbij het bestand Address.cs wordt genoemd. Vervang de inhoud door het volgende.
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; } } }
Volg opnieuw hetzelfde proces om de klasse Room te maken, en geef het bestand de naam 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; } } }
Het laatste model dat u in deze zelfstudie maakt, is een klasse met de naam SearchData en vertegenwoordigt de invoer van de gebruiker (searchText) en de uitvoer van de zoekopdracht (resultList). Het type uitvoer is essentieel, SearchResults<Hotel>, omdat dit type exact overeenkomt met de resultaten van de zoekopdracht en u deze verwijzing moet doorgeven aan de weergave. Vervang de standaardsjabloon door de volgende code.
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; } }
Een webpagina maken
Projectsjablonen worden geleverd met een aantal clientweergaven in de map Weergaven . De exacte weergaven zijn afhankelijk van de versie van Core .NET die u gebruikt (3.1 wordt gebruikt in dit voorbeeld). Voor deze zelfstudie wijzigt u Index.cshtml om de elementen van een zoekpagina op te nemen.
Verwijder de inhoud van Index.cshtml in zijn geheel en bouw het bestand opnieuw op in de volgende stappen.
In de zelfstudie worden twee kleine afbeeldingen in de weergave gebruikt: een Azure-logo en een zoekvergrotingspictogram (azure-logo.png en search.png). Kopieer de installatiekopieën van het GitHub-project naar de map wwwroot/images in uw project.
De eerste regel van Index.cshtml moet verwijzen naar het model dat wordt gebruikt om gegevens te communiceren tussen de client (de weergave) en de server (de controller). Dit is het SearchData-model dat eerder is gemaakt. Voeg deze regel toe aan het bestand Index.cshtml file.
@model FirstAzureSearchApp.Models.SearchData
Het is standaard gebruikelijk om een titel voor de weergave in te voeren, dus de volgende regels moeten zijn:
@{ ViewData["Title"] = "Home Page"; }
Voer na de titel een verwijzing in naar een HTML-opmaakmodel, dat u binnenkort gaat maken.
<head> <link rel="stylesheet" href="~/css/hotels.css" /> </head>
De hoofdtekst van de weergave verwerkt twee use cases. Eerst moet er een lege pagina worden opgegeven bij het eerste gebruik, voordat er zoektekst wordt ingevoerd. Ten tweede moet het naast het zoekvak ook resultaten verwerken voor herhaalde query's.
Als u beide gevallen wilt afhandelen, moet u controleren of het model dat is opgegeven voor de weergave null is. Een null-model geeft de eerste use-case aan (de eerste uitvoering van de app). Voeg het volgende toe aan het bestand Index.cshtml en lees de opmerkingen.
<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>
Voeg het opmaakmodel toe. Selecteer in Visual Studio inNieuw>bestand>de optie Opmaakmodel (met Algemeen gemarkeerd).
Vervang de code door het volgende. We gaan niet verder in op dit bestand, de stijlen zijn standaard-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; }
Sla het opmaakmodelbestand op als hotels.css in de map wwwroot/css , naast het standaardbestand site.css.
Hiermee is de weergave voltooid. Op dit moment zijn zowel de modellen als de weergaven voltooid. Alleen de controller blijft over om alles met elkaar te verbinden.
Methoden definiëren
Wijzig in deze stap de inhoud van Home Controller.
Open het HomeController.cs-bestand en vervang de using-instructies door het volgende.
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;
Index-methoden toevoegen
In een MVC-app is de methode Index() een standaardactiemethode voor elke controller. Hiermee wordt de HTML-pagina van de index geopend. De standaardmethode, die geen parameters gebruikt, wordt in deze zelfstudie gebruikt voor het starten van de toepassing: het weergeven van een lege zoekpagina.
In deze sectie breiden we de methode uit om een tweede use-case te ondersteunen: de pagina weergeven wanneer een gebruiker zoektekst heeft ingevoerd. Ter ondersteuning van dit geval wordt de indexmethode uitgebreid om een model als parameter te nemen.
Voeg de volgende methode toe na de standaard Index() -methode.
[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); }
Let op de async-declaratie van de methode en de await-aanroep naar RunQueryAsync. Deze trefwoorden zorgen voor het maken van asynchrone aanroepen en voorkomen zo dat threads op de server worden geblokkeerd.
Het catch-blok maakt gebruik van het standaardfoutmodel dat is gemaakt.
De foutafhandeling en andere standaardweergaven en -methoden bekijken
Afhankelijk van de versie van .NET Core die u gebruikt, wordt er een iets andere set standaardweergaven gemaakt. Voor .NET Core 3.1 zijn de standaardweergaven Index, Privacy en Fout. U kunt deze standaardpagina's bekijken wanneer u de app uitvoert en onderzoeken hoe ze worden verwerkt in de controller.
Verderop in deze zelfstudie gaat u de foutweergave testen.
In het GitHub-voorbeeld worden ongebruikte weergaven en de bijbehorende acties verwijderd.
De methode RunQueryAsync toevoegen
De aanroep van Azure Cognitive Search is ingekapseld in onze RunQueryAsync-methode.
Voeg eerst enkele statische variabelen toe om de Azure-service in te stellen en een aanroep om deze te initiëren.
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"); }
Voeg nu de RunQueryAsync-methode zelf toe.
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); }
Zorg er bij deze methode eerst voor dat de Azure-configuratie is gestart en stel vervolgens enkele zoekopties in. De optie Selecteren geeft aan welke velden in de resultaten moeten worden geretourneerd en komen dus overeen met de eigenschapsnamen in de hotelklasse . Als u Selecteren weglaat, worden alle niet-weergegeven velden geretourneerd, wat inefficiënt kan zijn als u alleen geïnteresseerd bent in een subset van alle mogelijke velden.
De asynchrone aanroep van zoeken formuleert de aanvraag (gemodelleerd als searchText) en het antwoord (gemodelleerd als searchResult). Als u fouten in deze code opspoort, is de klasse SearchResult een goede kandidaat voor het instellen van een onderbrekingspunt als u de inhoud van model.resultList wilt onderzoeken. U zou moeten merken dat het intuïtief is, waarbij alleen de gegevens worden verstrekt die u hebt aangevraagd en niet veel meer.
De app testen
Nu gaan we controleren of de app correct wordt uitgevoerd.
Selecteer Foutopsporing>Starten zonder foutopsporing of druk op F5. Als de app wordt uitgevoerd zoals verwacht, krijgt u de eerste indexweergave.
Voer een querytekenreeks in zoals 'strand' (of een tekst die u te binnen treedt) en klik op het zoekpictogram om de aanvraag te verzenden.
Probeer 'five star' in te voeren. U ziet dat deze query geen resultaten retourneert. Een geavanceerdere zoekopdracht zou 'five star' behandelen als synoniem voor 'luxury' en deze resultaten retourneren. Ondersteuning voor synoniemen is beschikbaar in Azure Cognitive Search, maar wordt niet behandeld in deze reeks zelfstudies.
Voer 'hot' in als zoektekst. Er worden geen vermeldingen geretourneerd met het woord 'hotel' erin. Onze zoekopdracht zoekt alleen naar hele woorden, maar er worden wel enkele resultaten opgehaald.
Probeer andere woorden: 'pool','sunshine', 'view', enzovoort. U zult zien dat Azure Cognitive Search op het eenvoudigste, maar nog steeds overtuigende niveau werkt.
Voorwaarden en fouten aan de rand testen
Het is belangrijk om te controleren of onze functies voor foutafhandeling naar behoren werken, zelfs wanneer alles perfect werkt.
Voer in de Index-methode, na de aanroep try { de regel Throw new Exception() in. Deze uitzondering dwingt een fout af wanneer u op tekst zoekt.
Voer de app uit, voer 'bar' in als zoektekst en klik op het zoekpictogram. De uitzondering moet de foutweergave tot gevolg hebben.
Belangrijk
Het wordt beschouwd als een beveiligingsrisico om interne foutnummers op foutpagina's te retourneren. Als uw app is bedoeld voor algemeen gebruik, volgt u de aanbevolen beveiligingsprocedures voor wat u moet retourneren wanneer er een fout optreedt.
Verwijder Throw new Exception() wanneer u tevreden bent dat de foutafhandeling werkt zoals het moet.
Opgedane kennis
Houd rekening met de volgende opgedane kennis van dit project:
- Een Azure Cognitive Search aanroep is beknopt en het is eenvoudig om de resultaten te interpreteren.
- Asynchrone aanroepen voegen een kleine hoeveelheid complexiteit toe aan de controller, maar zijn een best practice die de prestaties verbetert.
- Deze app heeft een eenvoudige tekstzoekopdracht uitgevoerd, gedefinieerd door wat is ingesteld in searchOptions. Deze ene klasse kan echter worden gevuld met veel leden die verfijning toevoegen aan een zoekopdracht. Met iets meer werk kun je deze app aanzienlijk krachtiger maken.
Volgende stappen
Als u de gebruikerservaring wilt verbeteren, voegt u meer functies toe, met name paginering (met behulp van paginanummers of oneindig schuiven) en automatisch aanvullen/suggesties. U kunt ook andere zoekopties overwegen (bijvoorbeeld geografische zoekopdrachten op hotels binnen een opgegeven straal van een bepaald punt) en volgorde van zoekresultaten.
Deze volgende stappen worden behandeld in de resterende zelfstudies. Laten we beginnen met paginering.