Självstudie: Ordna sökresultat med hjälp av .NET SDK
I den här självstudieserien har resultaten returnerats och visats i standardordning. I den här självstudien lägger du till primära och sekundära sorteringsvillkor. Som ett alternativ till beställning baserat på numeriska värden visar det sista exemplet hur du rangordnar resultat baserat på en anpassad bedömningsprofil. Vi kommer också att gå lite djupare in i visningen av komplexa typer.
I den här guiden får du lära dig att:
- Sortera resultat baserat på en egenskap
- Sortera resultat baserat på flera egenskaper
- Sortera resultat baserat på en bedömningsprofil
Översikt
Den här självstudien utökar det oändliga rullningsprojektet som skapades i självstudien Lägg till sidindelning i sökresultat .
En färdig version av koden i den här självstudien finns i följande projekt:
Förutsättningar
- 2b-add-infinite-scroll-lösning (GitHub). Det här projektet kan antingen vara din egen version som skapats från föregående självstudie eller en kopia från GitHub.
Sortera resultat baserat på en egenskap
När du beställer resultat baserat på en egenskap, till exempel hotellklassificering, vill vi inte bara ha de ordnade resultaten, vi vill också ha en bekräftelse på att ordern är korrekt. Genom att lägga till fältet Omdöme i resultaten kan vi bekräfta att resultaten sorteras korrekt.
I den här övningen kommer vi också att lägga till lite mer för att visa resultat: det billigaste rumspriset och det dyraste rumspriset för varje hotell.
Du behöver inte ändra någon av modellerna för att aktivera beställning. Endast vyn och kontrollanten kräver uppdateringar. Börja med att öppna hemstyrenheten.
Lägg till egenskapen OrderBy i sökparametrarna
I HomeController.cs lägger du till alternativet OrderBy och inkluderar egenskapen Rating med en fallande sorteringsordning. I metoden Index(SearchData model) lägger du till följande rad i sökparametrarna.
options.OrderBy.Add("Rating desc");
Anteckning
Standardordningen är stigande, men du kan lägga
asc
till i egenskapen för att göra detta tydligt. Fallande ordning anges genom att lägga tilldesc
.Kör nu appen och ange en vanlig sökterm. Resultaten kanske eller kanske inte är i rätt ordning, eftersom varken du som utvecklare, inte användaren, har något enkelt sätt att verifiera resultaten!
Nu ska vi klargöra att resultaten sorteras efter klassificering. Ersätt först klasserna box1 och box2 i filen hotels.css med följande klasser (dessa klasser är alla nya som vi behöver för den här självstudien).
textarea.box1A { width: 324px; height: 32px; border: none; background-color: azure; font-size: 14pt; color: blue; padding-left: 5px; text-align: left; } textarea.box1B { width: 324px; height: 32px; border: none; background-color: azure; font-size: 14pt; color: blue; text-align: right; padding-right: 5px; } textarea.box2A { width: 324px; height: 32px; border: none; background-color: azure; font-size: 12pt; color: blue; padding-left: 5px; text-align: left; } textarea.box2B { width: 324px; height: 32px; border: none; background-color: azure; font-size: 12pt; color: blue; text-align: right; padding-right: 5px; } textarea.box3 { width: 648px; height: 100px; border: none; background-color: azure; font-size: 12pt; padding-left: 5px; margin-bottom: 24px; }
Tips
Webbläsare cachelagrar vanligtvis css-filer, vilket kan leda till att en gammal CSS-fil används och dina redigeringar ignoreras. Ett bra sätt att avrunda detta är att lägga till en frågesträng med en versionsparameter till länken. Exempel:
<link rel="stylesheet" href="~/css/hotels.css?v1.1" />
Uppdatera versionsnumret om du tror att en gammal css-fil används av webbläsaren.
Lägg till egenskapen Rating i parametern Select i metoden Index(SearchData model) så att resultatet inkluderar följande tre fält:
options.Select.Add("HotelName"); options.Select.Add("Description"); options.Select.Add("Rating");
Öppna vyn (index.cshtml) och ersätt renderingsloopen (<!-- Visa hotelldata. -->) med följande kod.
<!-- Show the hotel data. --> @for (var i = 0; i < result.Count; i++) { var ratingText = $"Rating: {result[i].Document.Rating}"; // Display the hotel details. @Html.TextArea($"name{i}", result[i].Document.HotelName, new { @class = "box1A" }) @Html.TextArea($"rating{i}", ratingText, new { @class = "box1B" }) @Html.TextArea($"desc{i}", fullDescription, new { @class = "box3" }) }
Klassificeringen måste vara tillgänglig både på den första sidan som visas och på efterföljande sidor som anropas via den oändliga rullningen. För den senare av dessa två situationer måste vi uppdatera både åtgärden Nästa i kontrollanten och den rullningsna funktionen i vyn. Från och med kontrollanten ändrar du metoden Nästa till följande kod. Den här koden skapar och förmedlar klassificeringstexten.
public async Task<ActionResult> Next(SearchData model) { // Set the next page setting, and call the Index(model) action. model.paging = "next"; await Index(model); // Create an empty list. var nextHotels = new List<string>(); // Add a hotel details to the list. await foreach (var result in model.resultList.GetResultsAsync()) { var ratingText = $"Rating: {result.Document.Rating}"; var rateText = $"Rates from ${result.Document.cheapest} to ${result.Document.expensive}"; string fullDescription = result.Document.Description; // Add strings to the list. nextHotels.Add(result.Document.HotelName); nextHotels.Add(ratingText); nextHotels.Add(fullDescription); } // Rather than return a view, return the list of data. return new JsonResult(nextHotels); }
Uppdatera nu den rullningsade funktionen i vyn för att visa klassificeringstexten.
<script> function scrolled() { if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) { $.getJSON("/Home/Next", function (data) { var div = document.getElementById('myDiv'); // Append the returned data to the current list of hotels. for (var i = 0; i < data.length; i += 3) { div.innerHTML += '\n<textarea class="box1A">' + data[i] + '</textarea>'; div.innerHTML += '\n<textarea class="box1B">' + data[i + 1] + '</textarea>'; div.innerHTML += '\n<textarea class="box3">' + data[i + 2] + '</textarea>'; } }); } } </script>
Kör nu appen igen. Sök efter en vanlig term, till exempel "wifi", och kontrollera att resultaten sorteras efter fallande ordning efter hotellklassificering.
Du kommer att märka att flera hotell har ett identiskt omdöme, så deras utseende på skärmen är återigen den ordning som data hittas, vilket är godtyckligt.
Innan vi börjar lägga till en andra ordningsnivå ska vi lägga till kod för att visa intervallet med rumspriser. Vi lägger till den här koden för att både visa extrahering av data från en komplex typ och även så att vi kan diskutera beställningsresultat baserat på pris (billigast först kanske).
Lägg till intervallet med rumspriser i vyn
Lägg till egenskaper som innehåller den billigaste och dyraste rumspriset i Hotel.cs-modellen.
// Room rate range public double cheapest { get; set; } public double expensive { get; set; }
Beräkna rumspriserna i slutet av åtgärden Index (SearchData-modell) i hemkontrollanten. Lägg till beräkningarna efter lagringen av tillfälliga data.
// Ensure TempData is stored for the next call. TempData["page"] = page; TempData["searchfor"] = model.searchText; // Calculate the room rate ranges. await foreach (var result in model.resultList.GetResultsAsync()) { var cheapest = 0d; var expensive = 0d; foreach (var room in result.Document.Rooms) { var rate = room.BaseRate; if (rate < cheapest || cheapest == 0) { cheapest = (double)rate; } if (rate > expensive) { expensive = (double)rate; } } model.resultList.Results[n].Document.cheapest = cheapest; model.resultList.Results[n].Document.expensive = expensive; }
Lägg till egenskapen Rooms i parametern Select i åtgärdsmetoden Index(SearchData model) för kontrollanten.
options.Select.Add("Rooms");
Ändra återgivningsloopen i vyn för att visa frekvensintervallet för den första sidan med resultat.
<!-- Show the hotel data. --> @for (var i = 0; i < result.Count; i++) { var rateText = $"Rates from ${result[i].Document.cheapest} to ${result[i].Document.expensive}"; var ratingText = $"Rating: {result[i].Document.Rating}"; string fullDescription = result[i].Document.Description; // Display the hotel details. @Html.TextArea($"name{i}", result[i].Document.HotelName, new { @class = "box1A" }) @Html.TextArea($"rating{i}", ratingText, new { @class = "box1B" }) @Html.TextArea($"rates{i}", rateText, new { @class = "box2A" }) @Html.TextArea($"desc{i}", fullDescription, new { @class = "box3" }) }
Ändra metoden Nästa i startkontrollanten för att kommunicera frekvensintervallet för efterföljande resultatsidor.
public async Task<ActionResult> Next(SearchData model) { // Set the next page setting, and call the Index(model) action. model.paging = "next"; await Index(model); // Create an empty list. var nextHotels = new List<string>(); // Add a hotel details to the list. await foreach (var result in model.resultList.GetResultsAsync()) { var ratingText = $"Rating: {result.Document.Rating}"; var rateText = $"Rates from ${result.Document.cheapest} to ${result.Document.expensive}"; string fullDescription = result.Document.Description; // Add strings to the list. nextHotels.Add(result.Document.HotelName); nextHotels.Add(ratingText); nextHotels.Add(rateText); nextHotels.Add(fullDescription); } // Rather than return a view, return the list of data. return new JsonResult(nextHotels); }
Uppdatera den bläddrade funktionen i vyn för att hantera rumspristexten.
<script> function scrolled() { if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) { $.getJSON("/Home/Next", function (data) { var div = document.getElementById('myDiv'); // Append the returned data to the current list of hotels. for (var i = 0; i < data.length; i += 4) { div.innerHTML += '\n<textarea class="box1A">' + data[i] + '</textarea>'; div.innerHTML += '\n<textarea class="box1B">' + data[i + 1] + '</textarea>'; div.innerHTML += '\n<textarea class="box2A">' + data[i + 2] + '</textarea>'; div.innerHTML += '\n<textarea class="box3">' + data[i + 4] + '</textarea>'; } }); } } </script>
Kör appen och kontrollera att rumsprisintervallen visas.
Egenskapen OrderBy för sökparametrarna accepterar inte en post som Rooms.BaseRate för att tillhandahålla det billigaste rumspriset, även om rummen redan har sorterats enligt priset. I det här fallet sorteras rummen inte efter pris. För att kunna visa hotell i exempeldatauppsättningen, sorterade efter rumspris, skulle du behöva sortera resultaten i din hemkontrollant och skicka resultaten till vyn i önskad ordning.
Ordna resultat baserat på flera värden
Frågan är nu hur man skiljer mellan hotell med samma betyg. En metod kan vara en sekundär beställning baserat på den senaste gången hotellet renoverades så att mer nyligen renoverade hotell visas högre i resultaten.
Om du vill lägga till en andra sorteringsnivå lägger du till LastRenovationDate i sökresultaten och i OrderBy i metoden Index(SearchData model).
options.Select.Add("LastRenovationDate"); options.OrderBy.Add("LastRenovationDate desc");
Tips
Valfritt antal egenskaper kan anges i OrderBy-listan . Om hotellen hade samma betyg och renoveringsdatum kunde en tredje fastighet anges för att skilja mellan dem.
Återigen måste vi se renoveringsdatumet i vyn, bara för att vara säker på att beställningen är korrekt. För en sådan sak som en renovering räcker det förmodligen bara året. Ändra återgivningsloopen i vyn till följande kod.
<!-- Show the hotel data. --> @for (var i = 0; i < result.Count; i++) { var rateText = $"Rates from ${result[i].Document.cheapest} to ${result[i].Document.expensive}"; var lastRenovatedText = $"Last renovated: { result[i].Document.LastRenovationDate.Value.Year}"; var ratingText = $"Rating: {result[i].Document.Rating}"; string fullDescription = result[i].Document.Description; // Display the hotel details. @Html.TextArea($"name{i}", result[i].Document.HotelName, new { @class = "box1A" }) @Html.TextArea($"rating{i}", ratingText, new { @class = "box1B" }) @Html.TextArea($"rates{i}", rateText, new { @class = "box2A" }) @Html.TextArea($"renovation{i}", lastRenovatedText, new { @class = "box2B" }) @Html.TextArea($"desc{i}", fullDescription, new { @class = "box3" }) }
Ändra metoden Nästa i hemstyrenheten för att vidarebefordra årskomponenten för det senaste renoveringsdatumet.
public async Task<ActionResult> Next(SearchData model) { // Set the next page setting, and call the Index(model) action. model.paging = "next"; await Index(model); // Create an empty list. var nextHotels = new List<string>(); // Add a hotel details to the list. await foreach (var result in model.resultList.GetResultsAsync()) { var ratingText = $"Rating: {result.Document.Rating}"; var rateText = $"Rates from ${result.Document.cheapest} to ${result.Document.expensive}"; var lastRenovatedText = $"Last renovated: {result.Document.LastRenovationDate.Value.Year}"; string fullDescription = result.Document.Description; // Add strings to the list. nextHotels.Add(result.Document.HotelName); nextHotels.Add(ratingText); nextHotels.Add(rateText); nextHotels.Add(lastRenovatedText); nextHotels.Add(fullDescription); } // Rather than return a view, return the list of data. return new JsonResult(nextHotels); }
Ändra den rullad funktionen i vyn för att visa renoveringstexten.
<script> function scrolled() { if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) { $.getJSON("/Home/Next", function (data) { var div = document.getElementById('myDiv'); // Append the returned data to the current list of hotels. for (var i = 0; i < data.length; i += 5) { div.innerHTML += '\n<textarea class="box1A">' + data[i] + '</textarea>'; div.innerHTML += '\n<textarea class="box1B">' + data[i + 1] + '</textarea>'; div.innerHTML += '\n<textarea class="box2A">' + data[i + 2] + '</textarea>'; div.innerHTML += '\n<textarea class="box2B">' + data[i + 3] + '</textarea>'; div.innerHTML += '\n<textarea class="box3">' + data[i + 4] + '</textarea>'; } }); } } </script>
Kör appen. Sök efter en vanlig term, till exempel "pool" eller "view", och kontrollera att hotell med samma klassificering nu visas i fallande ordning efter renoveringsdatum.
Sortera resultat baserat på en bedömningsprofil
Exemplen som ges i självstudien hittills visar hur du beställer efter numeriska värden (klassificering och renoveringsdatum), vilket ger en exakt ordningsföljd. Vissa sökningar och vissa data lämpar sig dock inte för en så enkel jämförelse mellan två dataelement. För fulltextsökningsfrågor innehåller Cognitive Search begreppet rangordning. Bedömningsprofiler kan anges för att påverka hur resultaten rangordnas, vilket ger mer komplexa och kvalitativa jämförelser.
Bedömningsprofiler definieras i indexschemat. Flera bedömningsprofiler har konfigurerats för hotelldata. Nu ska vi titta på hur en bedömningsprofil definieras och sedan försöka skriva kod för att söka efter dem.
Så här definieras bedömningsprofiler
Bedömningsprofiler definieras i ett sökindex vid designtillfället. Det skrivskyddade hotellindexet som hanteras av Microsoft har tre bedömningsprofiler. Det här avsnittet utforskar bedömningsprofilerna och visar hur du använder i koden.
Nedan visas standardbedömningsprofilen för hotelldatauppsättningen, som används när du inte anger någon OrderBy - eller ScoringProfile-parameter . Den här profilen ökar poängen för ett hotell om söktexten finns i hotellets namn, beskrivning eller lista över taggar (bekvämligheter). Observera hur vikterna för poängsättningen gynnar vissa fält. Om söktexten visas i ett annat fält, som inte visas nedan, har den en vikt på 1. Ju högre poäng desto högre resultat visas i vyn.
{ "name": "boostByField", "text": { "weights": { "Tags": 3, "HotelName": 2, "Description": 1.5, "Description_fr": 1.5, } } }
Följande alternativa bedömningsprofil ökar poängen avsevärt om en angiven parameter innehåller en eller flera av listan över taggar (som vi kallar "bekvämligheter"). Huvudpunkten för den här profilen är att en parameter måste anges som innehåller text. Om parametern är tom eller inte anges utlöses ett fel.
{ "name":"boostAmenities", "functions":[ { "fieldName":"Tags", "freshness":null, "interpolation":"linear", "magnitude":null, "distance":null, "tag":{ "tagsParameter":"amenities" }, "type":"tag", "boost":5 } ], "functionAggregation":0 },
I den här tredje profilen ger hotellbetyget en betydande ökning av poängen. Det senaste renoverade datumet ökar också poängen, men bara om dessa data infaller inom 730 dagar (2 år) från det aktuella datumet.
{ "name":"renovatedAndHighlyRated", "functions":[ { "fieldName":"Rating", "freshness":null, "interpolation":"linear", "magnitude":{ "boostingRangeStart":0, "boostingRangeEnd":5, "constantBoostBeyondRange":false }, "distance":null, "tag":null, "type":"magnitude", "boost":20 }, { "fieldName":"LastRenovationDate", "freshness":{ "boostingDuration":"P730D" }, "interpolation":"quadratic", "magnitude":null, "distance":null, "tag":null, "type":"freshness", "boost":10 } ], "functionAggregation":0 }
Nu ska vi se om de här profilerna fungerar som vi tycker att de borde.
Lägga till kod i vyn för att jämföra profiler
Öppna filen index.cshtml och ersätt brödtextavsnittet <> med följande kod.
<body> @using (Html.BeginForm("Index", "Home", FormMethod.Post)) { <table> <tr> <td></td> <td> <h1 class="sampleTitle"> <img src="~/images/azure-logo.png" width="80" /> Hotels Search - Order Results </h1> </td> </tr> <tr> <td></td> <td> <!-- 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> <div class="searchBoxForm"> <b> Order: </b> @Html.RadioButtonFor(m => m.scoring, "Default") Default @Html.RadioButtonFor(m => m.scoring, "RatingRenovation") By numerical Rating @Html.RadioButtonFor(m => m.scoring, "boostAmenities") By Amenities @Html.RadioButtonFor(m => m.scoring, "renovatedAndHighlyRated") By Renovated date/Rating profile </div> </td> </tr> <tr> <td valign="top"> <div id="facetplace" class="facetchecks"> @if (Model != null && Model.facetText != null) { <h5 class="facetheader">Amenities:</h5> <ul class="facetlist"> @for (var c = 0; c < Model.facetText.Length; c++) { <li> @Html.CheckBoxFor(m => m.facetOn[c], new { @id = "check" + c.ToString() }) @Model.facetText[c] </li> } </ul> } </div> </td> <td> @if (Model != null && Model.resultList != null) { // Show the total result count. <p class="sampleText"> @Html.DisplayFor(m => m.resultList.Count) Results <br /> </p> <div id="myDiv" style="width: 800px; height: 450px; overflow-y: scroll;" onscroll="scrolled()"> <!-- Show the hotel data. --> @for (var i = 0; i < Model.resultList.Results.Count; i++) { var rateText = $"Rates from ${Model.resultList.Results[i].Document.cheapest} to ${Model.resultList.Results[i].Document.expensive}"; var lastRenovatedText = $"Last renovated: { Model.resultList.Results[i].Document.LastRenovationDate.Value.Year}"; var ratingText = $"Rating: {Model.resultList.Results[i].Document.Rating}"; string amenities = string.Join(", ", Model.resultList.Results[i].Document.Tags); string fullDescription = Model.resultList.Results[i].Document.Description; fullDescription += $"\nAmenities: {amenities}"; // Display the hotel details. @Html.TextArea($"name{i}", Model.resultList.Results[i].Document.HotelName, new { @class = "box1A" }) @Html.TextArea($"rating{i}", ratingText, new { @class = "box1B" }) @Html.TextArea($"rates{i}", rateText, new { @class = "box2A" }) @Html.TextArea($"renovation{i}", lastRenovatedText, new { @class = "box2B" }) @Html.TextArea($"desc{i}", fullDescription, new { @class = "box3" }) } </div> <script> function scrolled() { if (myDiv.offsetHeight + myDiv.scrollTop >= myDiv.scrollHeight) { $.getJSON("/Home/Next", function (data) { var div = document.getElementById('myDiv'); // Append the returned data to the current list of hotels. for (var i = 0; i < data.length; i += 5) { div.innerHTML += '\n<textarea class="box1A">' + data[i] + '</textarea>'; div.innerHTML += '<textarea class="box1B">' + data[i + 1] + '</textarea>'; div.innerHTML += '\n<textarea class="box2A">' + data[i + 2] + '</textarea>'; div.innerHTML += '<textarea class="box2B">' + data[i + 3] + '</textarea>'; div.innerHTML += '\n<textarea class="box3">' + data[i + 4] + '</textarea>'; } }); } } </script> } </td> </tr> </table> } </body>
Öppna filen SearchData.cs och ersätt klassen SearchData med följande kod.
public class SearchData { public SearchData() { } // Constructor to initialize the list of facets sent from the controller. public SearchData(List<string> facets) { facetText = new string[facets.Count]; for (int i = 0; i < facets.Count; i++) { facetText[i] = facets[i]; } } // Array to hold the text for each amenity. public string[] facetText { get; set; } // Array to hold the setting for each amenitity. public bool[] facetOn { get; set; } // The text to search for. public string searchText { get; set; } // Record if the next page is requested. public string paging { get; set; } // The list of results. public DocumentSearchResult<Hotel> resultList; public string scoring { get; set; } }
Öppna filen hotels.css och lägg till följande HTML-klasser.
.facetlist { list-style: none; } .facetchecks { width: 250px; display: normal; color: #666; margin: 10px; padding: 5px; } .facetheader { font-size: 10pt; font-weight: bold; color: darkgreen; }
Lägg till kod i kontrollanten för att ange en bedömningsprofil
Öppna hemstyrenhetsfilen. Lägg till följande using-instruktion (för att hjälpa till med att skapa listor).
using System.Linq;
I det här exemplet behöver vi det första anropet till Index för att göra lite mer än att bara returnera den första vyn. Metoden söker nu efter upp till 20 bekvämligheter att visa i vyn.
public async Task<ActionResult> Index() { InitSearch(); // Set up the facets call in the search parameters. SearchOptions options = new SearchOptions(); // Search for up to 20 amenities. options.Facets.Add("Tags,count:20"); SearchResults<Hotel> searchResult = await _searchClient.SearchAsync<Hotel>("*", options); // Convert the results to a list that can be displayed in the client. List<string> facets = searchResult.Facets["Tags"].Select(x => x.Value.ToString()).ToList(); // Initiate a model with a list of facets for the first view. SearchData model = new SearchData(facets); // Save the facet text for the next view. SaveFacets(model, false); // Render the view including the facets. return View(model); }
Vi behöver två privata metoder för att spara fasorna till tillfällig lagring och återställa dem från tillfällig lagring och fylla i en modell.
// Save the facet text to temporary storage, optionally saving the state of the check boxes. private void SaveFacets(SearchData model, bool saveChecks = false) { for (int i = 0; i < model.facetText.Length; i++) { TempData["facet" + i.ToString()] = model.facetText[i]; if (saveChecks) { TempData["faceton" + i.ToString()] = model.facetOn[i]; } } TempData["facetcount"] = model.facetText.Length; } // Recover the facet text to a model, optionally recoving the state of the check boxes. private void RecoverFacets(SearchData model, bool recoverChecks = false) { // Create arrays of the appropriate length. model.facetText = new string[(int)TempData["facetcount"]]; if (recoverChecks) { model.facetOn = new bool[(int)TempData["facetcount"]]; } for (int i = 0; i < (int)TempData["facetcount"]; i++) { model.facetText[i] = TempData["facet" + i.ToString()].ToString(); if (recoverChecks) { model.facetOn[i] = (bool)TempData["faceton" + i.ToString()]; } } }
Vi måste ange parametrarna OrderBy och ScoringProfile efter behov. Ersätt den befintliga metoden Index(SearchData model) med följande.
public async Task<ActionResult> Index(SearchData model) { try { InitSearch(); int page; if (model.paging != null && model.paging == "next") { // Recover the facet text, and the facet check box settings. RecoverFacets(model, true); // Increment the page. page = (int)TempData["page"] + 1; // Recover the search text. model.searchText = TempData["searchfor"].ToString(); } else { // First search with text. // Recover the facet text, but ignore the check box settings, and use the current model settings. RecoverFacets(model, false); // First call. Check for valid text input, and valid scoring profile. if (model.searchText == null) { model.searchText = ""; } if (model.scoring == null) { model.scoring = "Default"; } page = 0; } // Setup the search parameters. var options = new SearchOptions { SearchMode = SearchMode.All, // Skip past results that have already been returned. Skip = page * GlobalVariables.ResultsPerPage, // Take only the next page worth of results. Size = GlobalVariables.ResultsPerPage, // Include the total number of results. IncludeTotalCount = true, }; // Select the data properties to be returned. options.Select.Add("HotelName"); options.Select.Add("Description"); options.Select.Add("Tags"); options.Select.Add("Rooms"); options.Select.Add("Rating"); options.Select.Add("LastRenovationDate"); List<string> parameters = new List<string>(); // Set the ordering based on the user's radio button selection. switch (model.scoring) { case "RatingRenovation": // Set the ordering/scoring parameters. options.OrderBy.Add("Rating desc"); options.OrderBy.Add("LastRenovationDate desc"); break; case "boostAmenities": { options.ScoringProfile = model.scoring; // Create a string list of amenities that have been clicked. for (int a = 0; a < model.facetOn.Length; a++) { if (model.facetOn[a]) { parameters.Add(model.facetText[a]); } } if (parameters.Count > 0) { options.ScoringParameters.Add($"amenities-{ string.Join(',', parameters)}"); } else { // No amenities selected, so set profile back to default. options.ScoringProfile = ""; } } break; case "renovatedAndHighlyRated": options.ScoringProfile = model.scoring; break; default: break; } // For efficiency, the search call should be asynchronous, so use SearchAsync rather than Search. model.resultList = await _searchClient.SearchAsync<Hotel>(model.searchText, options); // Ensure TempData is stored for the next call. TempData["page"] = page; TempData["searchfor"] = model.searchText; TempData["scoring"] = model.scoring; SaveFacets(model, true); // Calculate the room rate ranges. await foreach (var result in model.resultList.GetResultsAsync()) { var cheapest = 0d; var expensive = 0d; foreach (var room in result.Document.Rooms) { var rate = room.BaseRate; if (rate < cheapest || cheapest == 0) { cheapest = (double)rate; } if (rate > expensive) { expensive = (double)rate; } } result.Document.cheapest = cheapest; result.Document.expensive = expensive; } } catch { return View("Error", new ErrorViewModel { RequestId = "1" }); } return View("Index", model); }
Läs igenom kommentarerna för var och en av växelvalen .
Vi behöver inte göra några ändringar i nästa åtgärd, om du har slutfört ytterligare kod för föregående avsnitt om beställning baserat på flera egenskaper.
Köra och testa appen
Kör appen. Du bör se en fullständig uppsättning bekvämligheter i vyn.
Om du väljer "Efter numeriskt omdöme" för beställning får du den numeriska ordning som du redan har implementerat i den här självstudien, där renoveringsdatum avgörs bland hotell med samma betyg.
Prova nu profilen "By amenities". Gör olika val av bekvämligheter och kontrollera att hotell med dessa bekvämligheter höjs upp i resultatlistan.
Prova profilen "By Renovated date/Rating" för att se om du får det du förväntar dig. Endast nyrenoverade hotell bör få en friskhetsökning .
Resurser
Mer information finns i följande Lägg till bedömningsprofiler i ett Azure Cognitive Search index.
Lärdomar
Överväg följande lärdomar från det här projektet:
- Användarna förväntar sig att sökresultaten sorteras, mest relevanta först.
- Data behöver struktureras så att beställningen är enkel. Vi kunde inte sortera på "billigaste" först, eftersom data inte är strukturerade för att göra det möjligt att ordna utan ytterligare kod.
- Det kan finnas många nivåer i ordningen för att skilja mellan resultat som har samma värde på en högre ordningsnivå.
- Det är naturligt att vissa resultat sorteras i stigande ordning (till exempel avstånd från en punkt) och vissa i fallande ordning (till exempel gästklassificering).
- Bedömningsprofiler kan definieras när numeriska jämförelser inte är tillgängliga eller inte tillräckligt smarta för en datauppsättning. Att bedöma varje resultat hjälper till att ordna och visa resultaten intelligent.
Nästa steg
Du har slutfört den här serien med C#-självstudier – du borde ha fått värdefull kunskap om Azure Cognitive Search API:er.
Mer information och självstudier finns i Utbildningskatalogen för Microsoft Learn eller andra självstudier i Azure Cognitive Search dokumentationen.