Öğretici: .NET SDK'sını kullanarak otomatik tamamlama ve öneriler ekleme

Kullanıcı bir arama kutusuna yazmaya başladığında otomatik tamamlama (typeahead sorguları ve önerilen sonuçlar) uygulamayı öğrenin. Bu öğreticide, otomatik olarak tamamlanan sorguları ve önerilen sonuçları ayrı ayrı ve sonra birlikte göstereceğiz. Bir kullanıcının kullanılabilir tüm sonuçları bulmak için yalnızca iki veya üç karakter yazması gerekebilir.

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

  • Öneri ekleme
  • Önerilere vurgu ekleme
  • Otomatik tamamlama ekleme
  • Otomatik tamamlama ve önerileri birleştirme

Genel Bakış

Bu öğretici, arama sonuçlarına sayfalama ekleme öğreticisine otomatik tamamlama ve önerilen sonuçlar ekler.

Bu öğreticideki kodun tamamlanmış bir sürümü aşağıdaki projede bulunabilir:

Önkoşullar

Öneri ekleme

Kullanıcıya alternatifler sunmanın en basit örneğiyle başlayalım: önerilen sonuçların açılan listesi.

  1. index.cshtml dosyasında TextBoxFor deyimini azureautosuggest olarak değiştirin@id.

     @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautosuggest" }) <input value="" class="searchBoxSubmit" type="submit">
    
  2. Bu deyimin ardından kapanış </div> dosyasından sonra bu betiği girin. Bu betik, önerilen sonuçların açılan listesini sunmak için açık kaynak jQuery UI kitaplığındaki Otomatik Tamamlama pencere öğesinden yararlanıyor.

    <script>
        $("#azureautosuggest").autocomplete({
            source: "/Home/SuggestAsync?highlights=false&fuzzy=false",
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            }
        });
    </script>
    

    Kimlik "azureautosuggest" , yukarıdaki betiği arama kutusuna bağlar. Pencere öğesinin kaynak seçeneği, iki sorgu parametresiyle Öneri API'sini çağıran bir Suggest yöntemine ayarlanır: vurgular ve benzerleri, her ikisi de bu örnekte false olarak ayarlanmıştır. Ayrıca, aramayı tetikleyebilmek için en az iki karakter gerekir.

Görünüme jQuery betiklerine başvuru ekleme

  1. jQuery kitaplığına erişmek için görünüm dosyasının <head> bölümünü aşağıdaki kodla değiştirin:

    <head>
        <meta charset="utf-8">
        <title>Typeahead</title>
        <link href="https://code.jquery.com/ui/1.12.1/themes/start/jquery-ui.css"
              rel="stylesheet">
        <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
        <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    
        <link rel="stylesheet" href="~/css/hotels.css" />
    </head>
    
  2. Yeni bir jQuery başvurusu sunduğumuzdan, _Layout.cshtml dosyasındaki ( Görünümler/Paylaşılan klasöründe) varsayılan jQuery başvuruyu kaldırmamız veya açıklama satırı yapmamız gerekir. Aşağıdaki satırları bulun ve gösterildiği gibi ilk betik satırını açıklama satırı yapın. Bu değişiklik, jQuery'ye çakışma başvurularını önler.

    <environment include="Development">
        <!-- <script src="~/lib/jquery/dist/jquery.js"></script> -->
        <script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
        <script src="~/js/site.js" asp-append-version="true"></script>
    </environment>
    

    Artık önceden tanımlanmış Otomatik Tamamlama jQuery işlevlerini kullanabiliriz.

Öneri eylemini denetleyiciye ekleme

  1. Giriş denetleyicisinde SuggestAsync eylemini ekleyin ( PageAsync eyleminden sonra).

    public async Task<ActionResult> SuggestAsync(bool highlights, bool fuzzy, string term)
    {
        InitSearch();
    
        // Setup the suggest parameters.
        var options = new SuggestOptions()
        {
            UseFuzzyMatching = fuzzy,
            Size = 8,
        };
    
        if (highlights)
        {
            options.HighlightPreTag = "<b>";
            options.HighlightPostTag = "</b>";
        }
    
        // Only one suggester can be specified per index. It is defined in the index schema.
        // The name of the suggester is set when the suggester is specified by other API calls.
        // The suggester for the hotel database is called "sg", and simply searches the hotel name.
        var suggestResult = await _searchClient.SuggestAsync<Hotel>(term, "sg", options).ConfigureAwait(false);
    
        // Convert the suggested query results to a list that can be displayed in the client.
        List<string> suggestions = suggestResult.Value.Results.Select(x => x.Text).ToList();
    
        // Return the list of suggestions.
        return new JsonResult(suggestions);
    }
    

    Boyut parametresi kaç sonuç döndürüleceği belirtir (belirtilmemişse, varsayılan değer 5'tir). Dizin oluşturulduğunda arama dizininde bir önericisi belirtilir. Microsoft tarafından barındırılan örnek oteller dizininde, önerinin adı "sg" olur ve yalnızca HotelName alanında önerilen eşleşmeleri arar.

    Benzer öğe eşleştirme, çıkışa en fazla bir düzenleme uzaklığıyla "yakın ıskalamalar" eklenmesini sağlar. Highlights parametresi true olarak ayarlanırsa, kalın HTML etiketleri çıkışa eklenir. Sonraki bölümde her iki parametreyi de true olarak ayarlayacağız.

  2. Bazı söz dizimi hataları alabilirsiniz. Öyleyse, aşağıdaki iki using deyimini dosyanın en üstüne ekleyin.

    using System.Collections.Generic;
    using System.Linq;
    
  3. Uygulamayı çalıştırın. Örneğin , "po" girdiğinizde bir dizi seçenek elde eder misiniz? Şimdi "pa" deneyin.

    *po* yazdıktan sonra iki öneri gösterilir

    Girdiğiniz harflerin bir sözcük başlatması ve yalnızca sözcüğün içine dahil edilmemesi gerektiğine dikkat edin.

  4. Görünüm betiğinde &benzerini true olarak ayarlayın ve uygulamayı yeniden çalıştırın. Şimdi "po" girin. Aramada bir harfin yanlış olduğunu varsayar.

    Benzer öğe true olarak ayarlanmış *pa* yazma

    İlginizi çekiyorsa, Azure Bilişsel Arama'daki Lucene sorgu söz dizimi belirsiz aramalarda kullanılan mantığı ayrıntılı olarak açıklar.

Önerilere vurgu ekleme

Highlights parametresini true olarak ayarlayarak önerilerin kullanıcıya görünümünü geliştirebiliriz. Ancak, önce kalın yazı metnini görüntülemek için görünüme kod eklememiz gerekir.

  1. Görünümde (index.cshtml), daha önce açıklanan betiğin "azureautosuggest" arkasına aşağıdaki betiği ekleyin.

    <script>
        var updateTextbox = function (event, ui) {
            var result = ui.item.value.replace(/<\/?[^>]+(>|$)/g, "");
            $("#azuresuggesthighlights").val(result);
            return false;
        };
    
        $("#azuresuggesthighlights").autocomplete({
            html: true,
            source: "/home/suggest?highlights=true&fuzzy=false&",
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            },
            select: updateTextbox,
            focus: updateTextbox
        }).data("ui-autocomplete")._renderItem = function (ul, item) {
            return $("<li></li>")
                .data("item.autocomplete", item)
                .append("<a>" + item.label + "</a>")
                .appendTo(ul);
        };
    </script>
    
  2. Şimdi metin kutusunun kimliğini değiştirerek aşağıdaki gibi okumasını sağlayın.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azuresuggesthighlights" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. Uygulamayı yeniden çalıştırdığınızda, girdiğiniz metni önerilerde kalın yazıyla görmeniz gerekir. "pa" yazmayı deneyin.

    Vurgulama ile *pa* yazma

    Yukarıdaki vurgulama betiğinde kullanılan mantık kusursuz değildir. Aynı adla iki kez görünen bir terim girerseniz, kalın sonuçlar tam olarak istediğiniz gibi değildir. "mo" yazmayı deneyin.

    Bir geliştiricinin yanıtlaması gereken sorulardan biri, bir betiğin ne zaman "yeterince iyi" çalıştığı ve ne zaman ilginçliklerinin ne zaman ele alınması gerektiğidir. Bu öğreticide daha fazla vurgulama işlemi yapmayacağız, ancak vurgulama verileriniz için etkili değilse kesin bir algoritma bulmak dikkate alınması gereken bir şeydir. Daha fazla bilgi için bkz . İsabet vurgulama.

Otomatik tamamlama ekleme

Önerilerden biraz farklı olan bir diğer çeşitleme de sorgu terimini tamamlayan otomatik tamamlamadır (bazen "type-ahead" olarak adlandırılır). Kullanıcı deneyimini geliştirmeden önce en basit uygulamayla başlayacağız.

  1. Önceki betiklerinizi izleyerek görünüme aşağıdaki betiği girin.

    <script>
        $("#azureautocompletebasic").autocomplete({
            source: "/Home/Autocomplete",
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            }
        });
    </script>
    
  2. Şimdi metin kutusunun kimliğini değiştirerek aşağıdaki gibi okumasını sağlayın.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocompletebasic" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. Giriş denetleyicisinde, SuggestAsync eyleminden sonra Otomatik TamamlamaAsync eylemini girin.

    public async Task<ActionResult> AutoCompleteAsync(string term)
    {
        InitSearch();
    
        // Setup the autocomplete parameters.
        var ap = new AutocompleteOptions()
        {
            Mode = AutocompleteMode.OneTermWithContext,
            Size = 6
        };
        var autocompleteResult = await _searchClient.AutocompleteAsync(term, "sg", ap).ConfigureAwait(false);
    
        // Convert the autocompleteResult results to a list that can be displayed in the client.
        List<string> autocomplete = autocompleteResult.Value.Results.Select(x => x.Text).ToList();
    
        return new JsonResult(autocomplete);
    }
    

    Öneriler için yaptığımız otomatik tamamlama aramasında "sg" olarak adlandırılan aynı öneri işlevini kullandığımıza dikkat edin (bu nedenle yalnızca otel adlarını otomatik tamamlamaya çalışıyoruz).

    Bir dizi AutocompleteMode ayarı vardır ve OneTermWithContext kullanıyoruz. Ek seçeneklerin açıklaması için Otomatik Tamamlama API'sine bakın.

  4. Uygulamayı çalıştırın. Açılan listede görüntülenen seçenek aralığının tek sözcükler olduğunu fark edin. "re" ile başlayan sözcükleri yazmayı deneyin. Daha fazla harf yazıldıkçe seçeneklerin sayısını nasıl azalttığına dikkat edin.

    Temel otomatik tamamlama ile yazma

    Bu durumda, daha önce çalıştırdığınız öneriler betiği büyük olasılıkla bu otomatik tamamlama betiğinden daha yararlıdır. Otomatik tamamlamanın daha kullanıcı dostu olmasını sağlamak için önerilen sonuçlarla kullanmayı göz önünde bulundurun.

Otomatik tamamlama ve önerileri birleştirme

Otomatik tamamlama ve önerileri birleştirmek seçeneklerimizin en karmaşıkıdır ve muhtemelen en iyi kullanıcı deneyimini sağlar. Tek istediğimiz, yazılan metinle satır içi olarak görüntülemek, metni otomatik tamamlamaya yönelik ilk Azure Bilişsel Arama seçeneğidir. Ayrıca, açılan liste olarak bir dizi öneri istiyoruz.

Genellikle "satır içi otomatik tamamlama" veya benzer bir ad olarak adlandırılan bu işlevi sunan kitaplıklar vardır. Ancak API'leri keşfedebilmeniz için bu özelliği yerel olarak uygulayacağız. Bu örnekte ilk olarak denetleyici üzerinde çalışmaya başlayacağız.

  1. Denetleyiciye, belirtilen sayıda öneriyle birlikte yalnızca bir otomatik tamamlama sonucu döndüren bir eylem ekleyin. Bu eylemi AutoCompleteAndSuggestAsync olarak adlandıracağız. Giriş denetleyicisinde, diğer yeni eylemlerinizi izleyerek aşağıdaki eylemi ekleyin.

    public async Task<ActionResult> AutoCompleteAndSuggestAsync(string term)
    {
        InitSearch();
    
        // Setup the type-ahead search parameters.
        var ap = new AutocompleteOptions()
        {
            Mode = AutocompleteMode.OneTermWithContext,
            Size = 1,
        };
        var autocompleteResult = await _searchClient.AutocompleteAsync(term, "sg", ap);
    
        // Setup the suggest search parameters.
        var sp = new SuggestOptions()
        {
            Size = 8,
        };
    
        // Only one suggester can be specified per index. The name of the suggester is set when the suggester is specified by other API calls.
        // The suggester for the hotel database is called "sg" and simply searches the hotel name.
        var suggestResult = await _searchClient.SuggestAsync<Hotel>(term, "sg", sp).ConfigureAwait(false);
    
        // Create an empty list.
        var results = new List<string>();
    
        if (autocompleteResult.Value.Results.Count > 0)
        {
            // Add the top result for type-ahead.
            results.Add(autocompleteResult.Value.Results[0].Text);
        }
        else
        {
            // There were no type-ahead suggestions, so add an empty string.
            results.Add("");
        }
    
        for (int n = 0; n < suggestResult.Value.Results.Count; n++)
        {
            // Now add the suggestions.
            results.Add(suggestResult.Value.Results[n].Text);
        }
    
        // Return the list.
        return new JsonResult(results);
    }
    

    Sonuç listesinin en üstünde bir otomatik tamamlama seçeneği ve ardından tüm öneriler döndürülür.

  2. Görünümde, ilk olarak açık gri otomatik tamamlama sözcüğünün kullanıcı tarafından girilen daha kalın metin altında işlenmesini sağlayan bir hile uygularız. HTML, bu amaç için göreli konumlandırmayı içerir. TextBoxFor deyimini (ve çevresindeki <div> deyimlerini) aşağıdakine dönüştürerek, altında olarak tanımlanan ikinci bir arama kutusunun normal arama kutumuzun hemen altında olduğunu ve bu arama kutusunu varsayılan konumunun 39 piksel dışına çektiğinizi unutmayın!

    <div id="underneath" class="searchBox" style="position: relative; left: 0; top: 0">
    </div>
    
    <div id="searchinput" class="searchBoxForm" style="position: relative; left: 0; top: -39px">
        @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocomplete" }) <input value="" class="searchBoxSubmit" type="submit">
    </div>
    

    Bu örnekte kimliği yeniden azureautocomplete olarak değiştirdiğimize dikkat edin.

  3. Ayrıca görünümde, şu ana kadar girdiğiniz tüm betiklerden sonra aşağıdaki betiği girin. Betik, işlediği çeşitli giriş davranışları nedeniyle uzun ve karmaşıktır.

    <script>
        $('#azureautocomplete').autocomplete({
            delay: 500,
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            },
    
            // Use Ajax to set up a "success" function.
            source: function (request, response) {
                var controllerUrl = "/Home/AutoCompleteAndSuggestAsync?term=" + $("#azureautocomplete").val();
                $.ajax({
                    url: controllerUrl,
                    dataType: "json",
                    success: function (data) {
                        if (data && data.length > 0) {
    
                            // Show the autocomplete suggestion.
                            document.getElementById("underneath").innerHTML = data[0];
    
                            // Remove the top suggestion as it is used for inline autocomplete.
                            var array = new Array();
                            for (var n = 1; n < data.length; n++) {
                                array[n - 1] = data[n];
                            }
    
                            // Show the drop-down list of suggestions.
                            response(array);
                        } else {
    
                            // Nothing is returned, so clear the autocomplete suggestion.
                            document.getElementById("underneath").innerHTML = "";
                        }
                    }
                });
            }
        });
    
        // Complete on TAB.
        // Clear on ESC.
        // Clear if backspace to less than 2 characters.
        // Clear if any arrow key hit as user is navigating the suggestions.
        $("#azureautocomplete").keydown(function (evt) {
    
            var suggestedText = document.getElementById("underneath").innerHTML;
            if (evt.keyCode === 9 /* TAB */ && suggestedText.length > 0) {
                $("#azureautocomplete").val(suggestedText);
                return false;
            } else if (evt.keyCode === 27 /* ESC */) {
                document.getElementById("underneath").innerHTML = "";
                $("#azureautocomplete").val("");
            } else if (evt.keyCode === 8 /* Backspace */) {
                if ($("#azureautocomplete").val().length < 2) {
                    document.getElementById("underneath").innerHTML = "";
                }
            } else if (evt.keyCode >= 37 && evt.keyCode <= 40 /* Any arrow key */) {
                document.getElementById("underneath").innerHTML = "";
            }
        });
    
        // Character replace function.
        function setCharAt(str, index, chr) {
            if (index > str.length - 1) return str;
            return str.substr(0, index) + chr + str.substr(index + 1);
        }
    
        // This function is needed to clear the "underneath" text when the user clicks on a suggestion, and to
        // correct the case of the autocomplete option when it does not match the case of the user input.
        // The interval function is activated with the input, blur, change, or focus events.
        $("#azureautocomplete").on("input blur change focus", function (e) {
    
            // Set a 2 second interval duration.
            var intervalDuration = 2000, 
                interval = setInterval(function () {
    
                    // Compare the autocorrect suggestion with the actual typed string.
                    var inputText = document.getElementById("azureautocomplete").value;
                    var autoText = document.getElementById("underneath").innerHTML;
    
                    // If the typed string is longer than the suggestion, then clear the suggestion.
                    if (inputText.length > autoText.length) {
                        document.getElementById("underneath").innerHTML = "";
                    } else {
    
                        // If the strings match, change the case of the suggestion to match the case of the typed input.
                        if (autoText.toLowerCase().startsWith(inputText.toLowerCase())) {
                            for (var n = 0; n < inputText.length; n++) {
                                autoText = setCharAt(autoText, n, inputText[n]);
                            }
                            document.getElementById("underneath").innerHTML = autoText;
    
                        } else {
                            // The strings do not match, so clear the suggestion.
                            document.getElementById("underneath").innerHTML = "";
                        }
                    }
    
                    // If the element loses focus, stop the interval checking.
                    if (!$input.is(':focus')) clearInterval(interval);
    
                }, intervalDuration);
        });
    </script>
    

    Interval işlevinin hem kullanıcının yazmakta olduğu metinle eşleşmediğinde temel alınan metni temizlemek hem de kullanıcıyla aynı büyük/küçük harf (üst veya alt) değerini ayarlamak için (arama sırasında "pa" "PA", "pA", "Pa" ile eşleşir) ve böylece büyük/küçük harfli metnin düzgün olmasını sağlamak için kullanıldığına dikkat edin.

    Daha iyi anlamak için betikteki açıklamaları okuyun.

  4. Son olarak, bunları saydam hale getirmek için iki HTML sınıfında küçük bir ayarlama yapmamız gerekir. aşağıdaki satırı hotels.css dosyasında searchBoxForm ve searchBox sınıflarına ekleyin.

    background: rgba(0,0,0,0);
    
  5. Şimdi uygulamayı çalıştırın. Arama kutusuna "pa" yazın. "Pa" içeren iki otelle birlikte otomatik tamamlama önerisi olarak "saray" mı alıyorsunuz?

    Satır içi otomatik tamamlama ve önerilerle yazma

  6. Otomatik tamamlama önerisini kabul etmek için sekmeyi deneyin, ok tuşlarını ve sekme tuşunu kullanarak önerileri seçmeyi deneyin ve fareyi ve tek tıklamayı kullanarak yeniden deneyin. Betiğin tüm bu durumları düzgün işlediğini doğrulayın.

    Bu özelliği size sunan bir kitaplığa yüklemenin daha kolay olduğuna karar vekleyebilirsiniz, ancak artık satır içi otomatik tamamlamanın en az bir yolunu biliyorsunuz.

Paketler

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

  • Otomatik tamamlama ("önceden yazma" olarak da bilinir) ve öneriler kullanıcının tam olarak ne istediğini bulmak için yalnızca birkaç anahtar yazmasına olanak sağlayabilir.
  • Otomatik tamamlama ve birlikte çalışma önerileri zengin bir kullanıcı deneyimi sağlayabilir.
  • Otomatik tamamlama işlevlerini her zaman tüm giriş biçimleriyle test edin.
  • setInterval işlevini kullanmak, kullanıcı arabirimi öğelerini doğrulama ve düzeltme konusunda yararlı olabilir.

Sonraki adımlar

Sonraki öğreticide, aramaları tek tıklamayla daraltmak için modelleri kullanarak kullanıcı deneyimini geliştirmenin başka bir yolunu inceleyeceğiz.