Freigeben über


Eine Such-App in ASP.NET Core erstellen

Erstellen Sie in diesem Tutorial eine einfache ASP.NET Core-App (Model View Controller), die im Localhost ausgeführt wird und eine Verbindung mit dem Hotelbeispielindex in Ihrem Suchdienst herstellt. In diesem Tutorial lernen Sie Folgendes:

  • Eine einfache Suchseite erstellen
  • Ergebnisse filtern
  • Ergebnisse sortieren

In diesem Tutorial liegt der Fokus auf serverseitigen Vorgängen, die über die Such-APIs aufgerufen werden. Obwohl es üblich ist, in clientseitigen Skripts zu sortieren und zu filtern, gibt Ihnen das Wissen, wie diese Vorgänge auf dem Server aufgerufen werden, mehr Möglichkeiten beim Entwerfen der Suchumgebung.

Den Beispielcode für dieses Tutorial finden Sie im Repository azure-search-dotnet-samples auf GitHub.

Voraussetzungen

Durchlaufen Sie den Assistenten zum Importieren von Daten, um den Index für Hotelstichproben für Ihren Suchdienst zu erstellen. Oder ändern Sie den Indexnamen in der Datei HomeController.cs.

Erstellen des Projekts

  1. Starten Sie Visual Studio, und wählen Sie Neues Projekt erstellen aus.

  2. Wählen Sie ASP.NET Core Web-App (Model View Controller) und dann Weiter aus.

  3. Geben Sie einen Projektnamen an, und wählen Sie dann Weiter aus.

  4. Wählen Sie auf der nächsten Seite .NET 6.0, .NET 7.0 oder .NET 8.0 aus.

  5. Vergewissern Sie sich, dass Keine Anweisungen der obersten Ebene verwenden nicht aktiviert ist.

  6. Klicken Sie auf Erstellen.

Hinzufügen von NuGet-Paketen

  1. Wählen Sie unter Tools die Option NuGet-Paket-Manager>NuGet-Pakete für die Lösung verwalten aus.

  2. Suchen Sie nach dem Paket Azure.Search.Documents, und installieren Sie die neuste stabile Version.

  3. Suchen Sie nach dem Paket Microsoft.Spatial, und installieren Sie es. Der Beispielindex enthält den Datentyp „GeographyPoint“. Durch die Installation dieses Pakets werden Laufzeitfehler vermieden. Alternativ können Sie das Feld „Standort“ aus der Hotelklasse entfernen, wenn Sie das Paket nicht installieren möchten. Dieses Feld wird in diesem Tutorial nicht verwendet.

Dienstinformationen hinzufügen

Für die Verbindung stellt die App Ihrer vollqualifizierten Such-URL einen Abfrage-API-Schlüssel vor. Beide werden in der Datei appsettings.json angegeben.

Ändern Sie appsettings.json, um Ihren Suchdienst und Abfrage-API-Schlüssel anzugeben.

{
    "SearchServiceUri": "<YOUR-SEARCH-SERVICE-URL>",
    "SearchServiceQueryApiKey": "<YOUR-SEARCH-SERVICE-QUERY-API-KEY>"
}

Sie können die Dienst-URL und den API-Schlüssel aus dem Portal abrufen. Da dieser Code einen Index abfragt und keinen erstellt, können Sie einen Abfrageschlüssel anstelle eines Administratorschlüssels verwenden.

Stellen Sie sicher, dass Sie den Suchdienst angeben, der über den hotels-sample-index verfügt.

Modelle hinzufügen

Erstellen Sie in diesem Schritt Modelle, die das Schema des hotels-sample-index darstellen.

  1. Wählen Sie im Projektmappen-Explorer mit der rechten Maustaste Modelle aus, und fügen Sie eine neue Klasse namens „Hotel“ für den folgenden Code hinzu:

     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; }
         }
     }
    
  2. Fügen Sie eine Klasse namens „Adresse“ hinzu, und ersetzen Sie sie durch den folgenden Code:

     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; }
         }
     }
    
  3. Fügen Sie eine Klasse namens „Räume“ hinzu, und ersetzen Sie sie durch den folgenden Code:

     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; }
         }
     }
    
  4. Fügen Sie eine Klasse namens „DatenDurchsuchen“ hinzu, und ersetzen Sie sie durch den folgenden Code:

     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;
         }
     }
    

Controller ändern

Ändern Sie in diesem Tutorial den Standardwert HomeController so, dass Methoden enthalten sind, die in Ihrem Suchdienst ausgeführt werden.

  1. Öffnen Sie im Projektmappen-Explorer unter ModelleHomeController.

  2. Ersetzen Sie den Standardcode durch den folgenden Inhalt:

    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();
             }
         }
     }
    

Ansicht ändern

  1. Öffnen Sie im Projektmappen-Explorer unter Ansichten>Startseiteindex.cshtml.

  2. Ersetzen Sie den Standardcode durch den folgenden Inhalt:

    @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>
    

Ausführen des Beispiels

  1. Drücken Sie F5, um das Projekt zu kompilieren und auszuführen. Die App wird auf dem lokalen Host ausgeführt und in Ihrem Standardbrowser geöffnet.

  2. Wählen Sie Suchen aus, um alle Ergebnisse zurückzugeben.

  3. Dieser Code verwendet die Standardsuchkonfiguration und unterstützt die einfache Syntax und searchMode=Any. Sie können Schlüsselwörter eingeben, mit booleschen Operatoren erweitern oder eine Präfixsuche ausführen (pool*).

Ändern Sie in den nächsten Abschnitten die Methode RunQueryAsync zu HomeController, um Filter und Sortierung hinzuzufügen.

Ergebnisse filtern

Indexfeldattribute bestimmen, welche Felder durchsuchbar, filterbar, sortierbar, facettierbar und abrufbar sind. Zu dem im Index für Hotelstichproben enthaltenen filterbaren Feldern gehören „Kategorie“, „Adresse/Stadt“ und „Adresse/BundeslandKanton“. In diesem Beispiel wird für „Kategorie“ ein $Filter-Ausdruck hinzugefügt.

Ein Filter wird immer zuerst ausgeführt, gefolgt von einer Abfrage, sofern eine angegeben wurde.

  1. Öffnen Sie HomeController, und suchen Sie die Methode RunQueryAsync. Fügen Sie Filter zu var options = new SearchOptions() hinzu:

     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);
     }
    
  2. Führen Sie die Anwendung aus.

  3. Klicken Sie auf Suchen, um eine leere Abfrage auszuführen. Mit den Filterkriterien werden anstelle der ursprünglichen 50 Dokumente nur 18 Dokumente zurückgegeben.

Weitere Informationen zu Filterausdrücken finden Sie unter Filter in Azure KI Search und OData-Syntax von „$filter“ in Azur KI Search.

Ergebnisse sortieren

Zu den im Index für Hotelstichproben enthaltenen sortierbaren Feldern gehören „Bewertung“ und „ZuletztRenoviert“. In diesem Beispiel wird dem Feld „Bewertung“ ein $OrderBy-Ausdruck hinzugefügt.

  1. Öffnen Sie die HomeController, und ersetzen Sie die Methode RunQueryAsync durch die folgende Version:

     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);
     }
    
  2. Führen Sie die Anwendung aus. Die Ergebnisse werden nach „Bewertung“ in absteigender Reihenfolge sortiert.

Weitere Informationen zum Sortieren finden Sie unter OData-Syntax von „$orderby“ in Azure KI Search.

Nächste Schritte

In diesem Tutorial haben Sie ein ASP.NET Core (MVC)-Projekt erstellt, das eine Verbindung mit einem Suchdienst hergestellt und Such-APIs für serverseitige Filterung und Sortierung aufgerufen hat.

Wenn Sie clientseitigen Code erkunden möchten, der auf Benutzeraktionen reagiert, sollten Sie ihrer Lösung eine React-Vorlage hinzufügen: