Öğretici: .NET SDK'sını kullanarak arama sonuçlarını sıralama

Bu öğretici serisi boyunca sonuçlar döndürüldü ve varsayılan sırada görüntülendi. Bu öğreticide, birincil ve ikincil sıralama ölçütlerini ekleyeceğiz. Sayısal değerlere göre sıralamaya alternatif olarak, son örnekte sonuçların özel puanlama profiline göre nasıl sıralanması gerektiği gösterilmektedir. Ayrıca karmaşık türlerin görüntüsünü biraz daha derine ineceğiz.

Bu öğreticide şunların nasıl yapıldığını öğreneceksiniz:

  • 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:

Ön koşullar

Sonuçları tek bir özelliğe göre sıralama

Otel derecelendirmesi gibi tek bir özelliğe dayalı olarak sonuçları sipariş ederken, yalnızca sipariş edilen sonuçları istemiyoruz, 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. Giriş denetleyicisini açarak başlayın.

OrderBy özelliğini arama parametrelerine ekleme

  1. HomeController.cs dosyasına OrderBy seçeneğini ekleyin ve azalan sıralama düzeniyle Rating özelliğini ekleyin. Index(SearchData modeli) yönteminde, arama parametrelerine aşağıdaki satırı ekleyin.

    options.OrderBy.Add("Rating desc");
    

    Not

    Varsayılan sıra artan düzendedir, ancak bunu net hale getirmek için özelliğine ekleyebilirsiniz asc . azalan düzen eklenerek descbelirtilir.

  2. Şimdi uygulamayı çalıştırın ve herhangi bir genel arama terimi girin. Sonuçlar doğru sırada olabilir veya olmayabilir, kullanıcı olarak değil geliştirici olarak sizin de sonuçları doğrulamanın kolay bir yolu vardır!

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

    İpucu

    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.

  4. 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");
    
  5. 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" })
    }
    
  6. Derecelendirmenin hem ilk görüntülenen sayfada hem de sonsuz kaydırma yoluyla çağrılan sonraki sayfalarda kullanılabilir olması gerekir. Bu iki durumun ikincisi için hem denetleyicideki Sonraki eylemini hem de görünümde kaydırılan işlevi güncelleştirmemiz 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);
    }
    
  7. Şimdi, derecelendirme metnini görüntülemek için görünümde kaydırılan işlevi 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 += 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>
    
  8. Ş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.

    Derecelendirmeye göre sıralama

    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 geçmeden önce, oda fiyatları aralığını görüntülemek için biraz 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üme oda fiyatları aralığını ekleme

  1. Hotel.cs modeline en ucuz ve en pahalı oda fiyatlarını içeren özellikler ekleyin.

    // Room rate range
    public double cheapest { get; set; }
    public double expensive { get; set; }
    
  2. Giriş denetleyicisindeki Index(SearchData modeli) 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;
    }
    
  3. Rooms özelliğini denetleyicinin Index(SearchData modeli) eylem yöntemindeki Select parametresine ekleyin.

    options.Select.Add("Rooms");
    
  4. İ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" })
    }
    
  5. Sonraki sonuç sayfalarında 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);
    }
    
  6. Oda fiyatları metnini işlemek için görünümde kaydırılan işlevi 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>
    
  7. Uygulamayı çalıştırın ve oda fiyatı aralıklarının görüntülendiğini doğrulayın.

    Oda fiyatı aralıklarını görüntüleme

Arama parametrelerinin OrderBy özelliği, oda fiyatına göre 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. Oda fiyatına göre sıralanmış örnek veri kümesindeki otelleri görüntülemek için ev denetleyicinizdeki sonuçları 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 sipariş olabilir, böylece yakın zamanda yenilenmiş oteller sonuçlarda daha yüksek görünür.

  1. İkinci bir sıralama düzeyi eklemek için, arama sonuçlarına LastRenovationDate ve Index(SearchData modeli) yönteminde OrderBy'ye ekleyin.

    options.Select.Add("LastRenovationDate");
    
    options.OrderBy.Add("LastRenovationDate desc");
    

    İpucu

    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.

  2. Yine, siparişin doğru olduğundan emin olmak için yenileme tarihini görünümde görmemiz gerekiyor. Tadilat 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" })
    }
    
  3. 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);
        }
    
  4. Yenileme metnini görüntülemek için görünümde kaydırılan işlevi 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>
    
  5. Uygulamayı çalıştırın. "Havuz" veya "görünüm" gibi ortak bir terim üzerinde arama yapın ve aynı derecelendirmeye sahip otellerin artık yenileme tarihine göre azalan düzende görüntülendiğini doğrulayın.

    Yenileme tarihinde sipariş verme

Puanlama profiline göre sonuçları sıralama

Öğreticide şu ana kadar verilen örneklerde sayısal değerlerin (derecelendirme ve yenileme tarihi) nasıl sıralanması ve tam bir sıralama dizisi sağlanması gösterildi. Ancak, bazı aramalar ve bazı veriler iki veri öğesi arasında bu kadar kolay bir karşılaştırma yapmak için kendilerini ödünç vermez. Tam metin arama sorguları için Bilişsel Arama , derecelendirme kavramını içerir. Puanlama profilleri , sonuçların derecelenme şeklini 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.

  1. 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, ağırlığı 1 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,
           }
       }
    }
    
  2. Aşağıdaki alternatif puanlama profili, sağlanan bir parametre etiket listesinden bir veya daha fazlasını içeriyorsa ("olanaklar" olarak adlandırılır) puanı önemli ölçüde artırır. Bu profilin temel noktası, metin içeren bir parametrenin 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
    },
    
  3. Bu üçüncü profilde, otel derecelendirmesi puana önemli bir artış sağlar. Son yenilenen tarih de puanı artırır, ancak yalnızca bu veriler geçerli tarihten itibaren 730 gün (2 yıl) içindeyse.

    {
        "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 olması gerektiğini düşündüğümüz şekilde çalışıp çalışmadıklarına bakalım.

Profilleri karşılaştırmak için görünüme kod ekleme

  1. 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>&nbsp;Order:&nbsp;</b>
                        @Html.RadioButtonFor(m => m.scoring, "Default") Default&nbsp;&nbsp;
                        @Html.RadioButtonFor(m => m.scoring, "RatingRenovation") By numerical Rating&nbsp;&nbsp;
                        @Html.RadioButtonFor(m => m.scoring, "boostAmenities") By Amenities&nbsp;&nbsp;
                        @Html.RadioButtonFor(m => m.scoring, "renovatedAndHighlyRated") By Renovated date/Rating profile&nbsp;&nbsp;
                    </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>
    
  2. 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; }       
    }
    
  3. 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

  1. Ev denetleyicisi dosyasını açın. Aşağıdaki using deyimini ekleyin (liste oluşturmaya yardımcı olmak için).

    using System.Linq;
    
  2. Bu örnekte, yalnızca ilk görünümü döndürmekten biraz daha fazlasını yapmak için dizine 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);
        }
    
  3. Modelleri geçici depolama alanına kaydetmek ve bunları geçici depolama alanından kurtarmak ve bir modeli doldurmak için iki özel yönteme ihtiyacımız vardır.

        // 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()];
                }
            }
        }
    
  4. OrderBy ve ScoringProfile parametrelerini gerektiği gibi ayarlamamız gerekir. Mevcut Index(SearchData modeli) yöntemini aşağıdakiyle 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 açıklamaları okuyun.

  5. Birden çok özelliğe göre sıralamaya göre ö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 etme

  1. Uygulamayı çalıştırın. Görünümde tam bir olanak kümesi görmeniz gerekir.

  2. Sıralama için "Sayısal Derecelendirmeye Göre" seçeneğinin seçilmesi, bu öğreticide zaten uyguladığınız sayısal sıralamayı verir ve yenileme tarihi eşit derecelendirmeye sahip oteller arasında karar verir.

    Derecelendirmeye göre

  3. Şimdi "Olanaklara göre" profilini deneyin. Çeşitli olanaklar seçin ve bu olanaklara sahip otellerin sonuç listesinde tanıtıldığını doğrulayın.

    Profile göre

  4. Beklediğiniz şeyi alıp almadığınıza bakmak için "Yenilenmiş tarih/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.

Paketler

Bu projeden aşağıdakileri göz önünde bulundurun:

  • Kullanıcılar önce arama sonuçlarının sıralanmasını ve en ilgili sonuçların sıralanmasını bekler.
  • Sıralamanın kolay olması için verilerin yapılandırılması gerekir. Veriler, sıralamanın ek kod olmadan yapılmasını sağlayacak şekilde yapılandırılmadığından ilk olarak "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ıralamada birçok düzey olabilir.
  • Bazı sonuçların artan düzende (örneğin, bir noktadan uzak mesafe) 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ıca 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.