Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu öğretici serisi boyunca sonuçlar, varsayılan sırada döndürülüp görüntülendi. Bu öğreticide birincil ve ikincil sıralama ölçütlerini ekleyebilirsiniz. Sayısal değerlere göre sıralamaya alternatif olarak, son örnekte sonuçların özel puanlama profiline göre nasıl sıralanması gösterilmektedir. Ayrıca karmaşık türlerin gösterimine biraz daha derinlemesine bakacağız.
Bu eğitimde şunları öğreniyorsunuz:
- Sonuçları tek bir özelliğe göre sıralama
- Sonuçları birden çok özelliğe göre sıralama
- Puanlama profiline göre sonuçları sıralama
Genel Bakış
Bu öğretici, Arama sonuçlarına sayfalama ekleme öğreticisinde oluşturulan sonsuz kaydırma projesini genişletir.
Bu öğreticideki kodun tamamlanmış bir sürümü aşağıdaki projede bulunabilir:
Önkoşullar
- 2b-add-infinite-scroll (GitHub) çözümü. Bu proje, önceki öğreticiden oluşturduğunuz kendi sürümünüz veya GitHub'dan alınmış bir kopya olabilir.
Sonuçları tek bir özelliğe göre sıralama
Otel derecelendirmesi gibi tek bir özelliğe göre sonuç sipariş ederken, sipariş edilen sonuçların yalnızca olmasını değil, aynı zamanda siparişin doğru olduğuna dair onay da istiyoruz. Sonuçlara Derecelendirme alanını eklemek, sonuçların doğru sıralandığından emin olmamıza olanak tanır.
Bu alıştırmada, sonuçların görüntülenmesine biraz daha fazla ekleyeceğiz: her otel için en ucuz oda fiyatı ve en pahalı oda fiyatı.
Sıralamayı etkinleştirmek için modellerden herhangi birini değiştirmeniz gerekmez. Yalnızca görünüm ve denetleyici güncelleştirme gerektirir. Ana denetleyiciyi açarak başlayın.
OrderBy özelliğini arama parametrelerine ekleme
HomeController.cs OrderBy seçeneğini ekleyin ve azalan sıralama düzeniyle Derecelendirme özelliğini ekleyin. Index(SearchData modeli) yönteminde, arama parametrelerine aşağıdaki satırı ekleyin.
options.OrderBy.Add("Rating desc");Uyarı
Varsayılan düzen artan düzendedir, ancak bunu net hale getirmek için özelliğine ekleyebilirsiniz
asc. Azalan düzen eklenerekdescbelirtilir.Şimdi uygulamayı çalıştırın ve ortak bir arama terimi girin. Sonuçlar doğru sırada olabilir veya olmayabilir, çünkü ne siz bir geliştirici olarak ne de kullanıcı olarak sonuçları doğrulamanın kolay bir yoluna sahip değilsiniz!
Sonuçların derecelendirmeye göre sıralandığından emin olalım. İlk olarak, hotels.css dosyasındaki box1 ve box2 sınıflarını aşağıdaki sınıflarla değiştirin (bu sınıflar bu öğretici için ihtiyacımız olan tüm yeni sınıflardır).
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; }Tavsiye
Tarayıcılar genellikle css dosyalarını önbelleğe alır ve bu, eski bir css dosyasının kullanılmasına ve düzenlemelerinizin yoksayılmasıyla sonuçlanabilir. Bunun iyi bir yolu, bağlantıya sürüm parametresine sahip bir sorgu dizesi eklemektir. Örneğin:
<link rel="stylesheet" href="~/css/hotels.css?v1.1" />Tarayıcınız tarafından eski bir css dosyasının kullanıldığını düşünüyorsanız sürüm numarasını güncelleştirin.
Sonuçların aşağıdaki üç alanı içermesi için Rating özelliğini Index(SearchData modeli) yöntemindeki Select parametresine ekleyin:
options.Select.Add("HotelName"); options.Select.Add("Description"); options.Select.Add("Rating");Görünümü (index.cshtml) açın ve işleme döngüsünü (<-- Otel verilerini göster. -->) aşağıdaki kodla değiştirin.
<!-- 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" }) }Derecelendirmenin hem ilk görüntülenen sayfada hem de sonsuz kaydırma aracılığıyla çağrılan sonraki sayfalarda kullanılabilir olması gerekir. Bu iki durumun ikincisi için hem denetleyicideki Sonraki eylemini hem de görünümdeki kaydırıldı işlevini güncellememiz gerekir. Denetleyiciden başlayarak Next yöntemini aşağıdaki kodla değiştirin. Bu kod derecelendirme metnini oluşturur ve iletir.
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); }Şimdi derecelendirme metnini görüntülemek için görünümdeki scroll işlevini güncelleyin.
<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>Şimdi uygulamayı yeniden çalıştırın. "Wifi" gibi herhangi bir yaygın terimi arayın ve sonuçların otel derecelendirmesinin azalan sırasına göre sıralandığını doğrulayın.
Birkaç otelin aynı derecelendirmeye sahip olduğunu fark edeceksiniz ve bu nedenle ekrandaki görünümleri yine verilerin bulunduğu sıradır ve bu rastgele bir durumdur.
İkinci bir sıralama düzeyi eklemeye başlamadan önce, oda fiyatları aralığını görüntülemek için kod ekleyelim. Bu kodu hem karmaşık bir türden veri ayıklamayı göstermek için hem de fiyata göre sıralama sonuçlarını tartışabilmek için ekliyoruz (belki de en ucuzu).
Görünümde oda fiyatları aralığını ekleyin
Hotel.cs modeline en ucuz ve en pahalı oda oranını içeren özellikler ekleyin.
// Room rate range public double cheapest { get; set; } public double expensive { get; set; }Ana denetleyicindeki Index(SearchData model) eyleminin sonunda oda fiyatlarını hesaplayın. Geçici verilerin depolanmasından sonra hesaplamaları ekleyin.
// 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; }Rooms özelliğini denetleyicinin Index(SearchData modeli) eylem yöntemindeki Select parametresine ekleyin.
options.Select.Add("Rooms");İlk sonuç sayfasının hız aralığını görüntülemek için görünümdeki işleme döngüsünü değiştirin.
<!-- 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" }) }Sonraki sonuç sayfaları için hız aralığını iletmek için giriş denetleyicisindeki Next yöntemini değiştirin.
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); }Oda fiyatları metnini işlemek için görünüm içindeki kaydırma işlevini güncelleştirin.
<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>Uygulamayı çalıştırın ve oda fiyatı aralıklarının görüntülendiğini doğrulayın.
Arama parametrelerinin OrderBy özelliği, odalar fiyat temelinde zaten sıralanmış olsa bile en ucuz oda fiyatı sağlamak için Rooms.BaseRate gibi bir girişi kabul etmeyecektir. Bu durumda odalar ücrete göre sıralanmaz. Otelleri oda fiyatına göre sıralanmış örnek veri kümesinde görüntülemek için sonuçları ev denetleyicinizde sıralamanız ve bu sonuçları istediğiniz sırada görünüme göndermeniz gerekir.
Sonuçları birden çok değere göre sıralama
Şimdi soru, aynı derecelendirmeye sahip oteller arasında nasıl ayrım yapılacağını öğrenmektir. Bir yaklaşım, otelin en son yenilenme zamanına göre ikincil bir sıralama olabilir, böylece daha yakın zamanda yenilenmiş oteller sonuçlarda daha yüksek görünür.
İkinci bir sıralama düzeyi eklemek için, Arama sonuçlarına LastRenovationDate ve Index(SearchData modeli) yöntemindeki OrderBy'e ekleyin.
options.Select.Add("LastRenovationDate"); options.OrderBy.Add("LastRenovationDate desc");Tavsiye
OrderBy listesine herhangi bir sayıda özellik girilebilir. Oteller aynı derecelendirme ve yenileme tarihine sahipse, aralarında ayrım yapmak için üçüncü bir tesis girilebilir.
Sıralamanın doğru olduğundan emin olmak için, yine yenileme tarihini görünümde görmemiz gerekiyor. Yenileme gibi bir şey için, muhtemelen sadece yıl yeterlidir. Görünümdeki işleme döngüsünü aşağıdaki kodla değiştirin.
<!-- 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" }) }Son yenileme tarihinin yıl bileşenini iletmek için ev denetleyicisindeki Next yöntemini değiştirin.
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); }Görünümdeki kaydırma işlevini yenileme metnini görüntüleyecek şekilde değiştirin.
<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>Uygulamayı çalıştırın. "Havuz" veya "görünüm" gibi ortak bir terim üzerinde arama yapın ve aynı derecelendirmeye sahip olan otellerin artık yenileme tarihine göre azalan düzende görüntülendiğini doğrulayın.
Puanlama profiline göre sonuçları sıralama
Öğreticide şu ana kadar verilen örnekler, tam bir sıralama sırası sağlayarak sayısal değerlerin (derecelendirme ve yenileme tarihi) nasıl sıralanması gerektiğini göstermektedir. Ancak bazı aramalar ve bazı veriler, iki veri öğesi arasında bu kadar kolay bir karşılaştırma gerçekleştirmez. Tam metin arama sorguları için Bilişsel Arama derecelendirme kavramını içerir. Puanlama profilleri , sonuçların derecesini etkilemek için belirtilebilir ve daha karmaşık ve nitel karşılaştırmalar sağlar.
Puanlama profilleri dizin şemasında tanımlanır. Otel verilerinde çeşitli puanlama profilleri ayarlanmıştır. Şimdi puanlama profilinin nasıl tanımlandığına bakalım ve sonra bu profillerde arama yapmak için kod yazmayı deneyelim.
Puanlama profilleri nasıl tanımlanır?
Puanlama profilleri, tasarım zamanında arama dizininde tanımlanır. Microsoft tarafından barındırılan salt okunur oteller dizini üç puanlama profiline sahiptir. Bu bölümde puanlama profilleri incelenip kodun nasıl kullanılacağı gösterilmektedir.
Aşağıda, herhangi bir OrderBy veya ScoringProfile parametresi belirtmediğinizde kullanılan otel veri kümesi için varsayılan puanlama profili yer alır. Bu profil, arama metni otel adında, açıklamasında veya etiket listesinde (olanaklar) mevcutsa otel puanını artırır. Puanlamanın ağırlıklarının belirli alanları nasıl desteklediğine dikkat edin. Arama metni aşağıda listelenmeyen başka bir alanda görünürse, 1 ağırlığa sahip olur. Açıkçası, puan ne kadar yüksek olursa, görünümde o kadar yüksek bir sonuç görünür.
{ "name": "boostByField", "text": { "weights": { "Tags": 3, "HotelName": 2, "Description": 1.5, "Description_fr": 1.5, } } }Aşağıdaki alternatif puanlama profili, sağlanan bir parametre etiket listesinden bir veya daha fazlasını içeriyorsa ("olanaklar" olarak adlandırdığımız) puanı önemli ölçüde artırır. Bu profilin önemli noktası, metin içeren bir parametre sağlanması gerektiğidir . Parametre boşsa veya sağlanmazsa bir hata oluşur.
{ "name":"boostAmenities", "functions":[ { "fieldName":"Tags", "freshness":null, "interpolation":"linear", "magnitude":null, "distance":null, "tag":{ "tagsParameter":"amenities" }, "type":"tag", "boost":5 } ], "functionAggregation":0 },Bu üçüncü profilde, otel derecelendirmesi puana önemli bir artış sağlar. Son yenilenme tarihi de puanı artırır, ancak yalnızca bu veriler geçerli tarihten itibaren 730 gün (2 yıl) içinde kalırsa.
{ "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 }Şimdi bu profillerin gerektiği gibi çalışıp çalışmadıklarını görelim.
Profilleri karşılaştırmak için görünüme kod ekleme
index.cshtml dosyasını açın ve gövde> bölümünü aşağıdaki kodla değiştirin<.
<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>SearchData.cs dosyasını açın ve SearchData sınıfını aşağıdaki kodla değiştirin.
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; } }hotels.css dosyasını açın ve aşağıdaki HTML sınıflarını ekleyin.
.facetlist { list-style: none; } .facetchecks { width: 250px; display: normal; color: #666; margin: 10px; padding: 5px; } .facetheader { font-size: 10pt; font-weight: bold; color: darkgreen; }
Puanlama profili belirtmek için denetleyiciye kod ekleme
Ana denetleyici dosyasını açın. Aşağıdaki using deyimini ekleyin (liste oluşturmaya yardımcı olmak için).
using System.Linq;Bu örnekte, yalnızca ilk görünümü döndürmekten biraz daha fazlasını yapmak için Dizin'e ilk çağrıya ihtiyacımız vardır. Yöntemi artık görünümde görüntülenecek en fazla 20 olanak arar.
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); }Geçici depolama alanına yönleri kaydetmek ve bu yönleri geçici depolama alanından kurtarıp yeni bir model oluşturmak için iki özel metoda ihtiyacımız var.
// 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()]; } } }OrderBy ve ScoringProfile parametrelerini gerektiği gibi ayarlamamız gerekir. Mevcut Index(SearchData modeli) yöntemini aşağıdakilerle değiştirin.
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); }Geçiş seçimlerinin her biri için yorumları okuyun.
Birden çok özelliğe göre sıralamayla ilgili önceki bölümün ek kodunu tamamladıysanız , Sonraki eyleminde herhangi bir değişiklik yapmamız gerekmez.
Uygulamayı çalıştırma ve test edin
Uygulamayı çalıştırın. Görünümde eksiksiz bir olanak kümesi görmeniz gerekir.
Sıralama için "Sayısal Derecelendirmeye Göre" seçeneğini seçtiğinizde, bu öğreticide zaten uygulamış olduğunuz sayısal sıralama sağlanacak ve yenileme tarihi, eşit derecelendirmeye sahip oteller arasında seçim yapacaktır.
Şimdi "Tesislere göre" profilini deneyin. Çeşitli olanaklar seçin ve bu olanaklara sahip otellerin sonuç listesinde tanıtıldığını doğrulayın.
Beklediğiniz şeyi alıp almadığınıza bakmak için "Yenilenen tarihe/Derecelendirme profiline göre" öğesini deneyin. Sadece yakın zamanda yenilenmiş oteller tazelik artışı almalıdır.
Kaynaklar
Daha fazla bilgi için aşağıdaki Azure Bilişsel Arama dizinine puanlama profilleri ekleme bölümüne bakın.
Çıkarımlar
Bu projeden aşağıdakileri göz önünde bulundurun:
- Kullanıcılar, arama sonuçlarının sıralanmasını bekler ve önce en ilgili sonuçları alır.
- Verilerin, sıralamanın kolay olması için yapılandırılması gerekir. Veriler ek kod olmadan sıralamayı etkinleştirecek şekilde yapılandırılmadığından önce "en ucuz" sıralamayı kolayca gerçekleştiremedik.
- Daha yüksek bir sıralama düzeyinde aynı değere sahip sonuçlar arasında ayrım yapmak için sıralamanın birçok düzeyi olabilir.
- Bazı sonuçların artan düzende (örneğin, bir noktadan uzak) ve bazılarının azalan sırada (örneğin, konuğun derecelendirmesi) sıralanması doğaldır.
- Puanlama profilleri, bir veri kümesi için sayısal karşılaştırmalar kullanılamadığında veya yeterince akıllı olmadığında tanımlanabilir. Her sonucu puanlama, sonuçları akıllı bir şekilde sıralamaya ve görüntülemeye yardımcı olur.
Sonraki Adımlar
Bu C# öğretici dizisini tamamladınız. Azure Bilişsel Arama API'leri hakkında değerli bilgiler edinmiş olmanız gerekir.
Daha fazla başvuru ve öğretici için Microsoft Learn eğitim kataloğuna veya Azure Bilişsel Arama belgelerindeki diğer öğreticilere göz atabilirsiniz.