Sdílet prostřednictvím


Kurz: Přidání automatického dokončování a návrhů pomocí sady .NET SDK

Zjistěte, jak implementovat automatické dokončování (dotazy na klávesnici a navrhované výsledky), když uživatel začne psát do vyhledávacího pole. V tomto kurzu zobrazíme automaticky dokončování dotazů a navrhovaných výsledků odděleně a pak společně. K vyhledání všech dostupných výsledků může uživatel zadat pouze dva nebo tři znaky.

V tomto kurzu se naučíte:

  • Přidání návrhů
  • Přidání zvýraznění k návrhům
  • Přidat automatické dokončování
  • Kombinování automatického dokončování a návrhů

Přehled

Tento kurz přidá automatické dokončování a navrhované výsledky do předchozího kurzu Přidání stránkování do výsledků hledání .

Dokončenou verzi kódu v tomto kurzu najdete v následujícím projektu:

Požadavky

Přidání návrhů

Začněme nejjednodušším případem, kdy uživateli nabídneme alternativy: rozevírací seznam navrhovaných výsledků.

  1. V souboru index.cshtml změňte @id příkaz TextBoxFor na azureautosuggest.

     @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautosuggest" }) <input value="" class="searchBoxSubmit" type="submit">
    
  2. Za tímto příkazem zadejte za uzavírací </div> tento skript. Tento skript využívá widget automatického dokončování z opensourcové knihovny uživatelského rozhraní jQuery k zobrazení rozevíracího seznamu navrhovaných výsledků.

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

    ID "azureautosuggest" připojí výše uvedený skript k vyhledávacímu poli. Zdrojová možnost widgetu je nastavená na metodu Suggest, která volá rozhraní API Pro návrhy se dvěma parametry dotazu: highlights (zvýraznění ) a fuzzy (přibližné hodnoty), oba jsou v tomto případě nastavené na false (false). K aktivaci vyhledávání jsou také potřeba minimálně dva znaky.

Přidání odkazů na skripty jQuery do zobrazení

  1. Pokud chcete získat přístup ke knihovně jQuery, změňte <> hlavní část souboru zobrazení na následující kód:

    <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. Protože zavádíme nový odkaz jQuery, musíme také odebrat nebo zakomentovat výchozí odkaz jQuery v souboru _Layout.cshtml (ve složce Views/Shared ). Vyhledejte následující řádky a okomentujte první řádek skriptu, jak je znázorněno na obrázku. Tato změna zabrání kolidování odkazů na jQuery.

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

    Teď můžeme použít předdefinované funkce jQuery automatického dokončování.

Přidání akce Navrhnout do kontroleru

  1. Na domovském ovladači přidejte akci SuggestAsync (za akci PageAsync ).

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

    Parametr Size určuje, kolik výsledků se má vrátit (pokud není zadaný, výchozí hodnota je 5). Při vytvoření indexu vyhledávání je v indexu vyhledávání zadána funkce navrhovatele . V indexu ukázkových hotelů hostovaném Microsoftem je název navrhovatele "sg" a hledá navrhované shody výhradně v poli HotelName .

    Přibližné porovnávání umožňuje zahrnout do výstupu "téměř zmeškané hodnoty", a to až do jedné editační vzdálenosti. Pokud je parametr highlights nastavený na true, pak se do výstupu přidají tučné značky HTML. Oba parametry nastavíme na true v další části.

  2. Může se zobrazit několik chyb syntaxe. Pokud ano, přidejte na začátek souboru následující dva příkazy using .

    using System.Collections.Generic;
    using System.Linq;
    
  3. Spustit aplikaci. Získáte řadu možností, například když zadáte "po"? Teď zkuste "pa".

    Při psaní *po* se zobrazí dva návrhy.

    Všimněte si, že písmena, která zadáte, musí začínat slovem a nesmí být jednoduše zahrnuta do slova.

  4. Ve skriptu zobrazení nastavte &fuzzy na true a spusťte aplikaci znovu. Teď zadejte "po". Všimněte si, že hledání předpokládá, že jste dostali špatné jedno písmeno.

    Psaní *pa* s přibližnou shodou nastavenou na true

    Pokud vás to zajímá, syntaxe dotazu Lucene v Azure Cognitive Search podrobně popisuje logiku používanou při přibližném vyhledávání.

Přidání zvýraznění k návrhům

Vzhled návrhů pro uživatele můžeme vylepšit nastavením parametru highlights na true. Nejdřív ale musíme do zobrazení přidat kód, který zobrazí tučný text.

  1. V zobrazení (index.cshtml) přidejte následující skript za "azureautosuggest" skript popsaný výše.

    <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. Teď změňte ID textového pole tak, aby se četlo takto.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azuresuggesthighlights" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. Spusťte aplikaci znovu a v návrzích byste měli vidět zadaný text tučným písmem. Zkuste zadat "pa".

    Psaní *pa* se zvýrazněním

    Logika použitá ve zvýrazňovacím skriptu výše není oklamatá. Pokud zadáte termín, který se zobrazí dvakrát ve stejném názvu, nebudou výsledky tučně přesně tak, jak byste chtěli. Zkuste zadat "mo".

    Jednou z otázek, na které musí vývojář odpovědět, je, kdy skript funguje "dostatečně dobře" a kdy by měl být vyřešen jeho věrný problém. V tomto kurzu nebudeme dále zvýrazňovat, ale nalezení přesného algoritmu je něco, co byste měli zvážit, pokud zvýraznění není pro vaše data efektivní. Další informace najdete v tématu Zvýraznění přístupů.

Přidat automatické dokončování

Další variantou, která se mírně liší od návrhů, je automatické dokončování (někdy označované jako "dopředný typ"), které dokončí termín dotazu. Znovu začneme s nejjednodušší implementací, a teprve pak vylepšíme uživatelské prostředí.

  1. Do zobrazení zadejte následující skript za předchozími skripty.

    <script>
        $("#azureautocompletebasic").autocomplete({
            source: "/Home/Autocomplete",
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            }
        });
    </script>
    
  2. Teď změňte ID textového pole tak, aby se četl takto.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocompletebasic" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. V domovském ovladači zadejte akci AutocompleteAsync za akci SuggestAsync .

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

    Všimněte si, že při hledání automatického dokončování používáme stejnou funkci navrhovatele sg jako u návrhů (proto se snažíme automaticky dokončovat jenom názvy hotelů).

    Existuje řada nastavení Automatické dokončováníMode a používáme OneTermWithContext. Popis dalších možností najdete v tématu rozhraní API pro automatické dokončování.

  4. Spustit aplikaci. Všimněte si, že rozsah možností zobrazený v rozevíracím seznamu je jedno slovo. Zkuste zadat slova začínající na "re". Všimněte si, jak se při psaní více písmen snižuje počet možností.

    Psaní se základním automatickým dokončováním

    Skript návrhů, který jste spustili dříve, je pravděpodobně užitečnější než tento skript automatického dokončování. Pokud chcete, aby bylo automatické dokončování uživatelsky přívětivější, zvažte jeho použití s navrhovanými výsledky.

Kombinování automatického dokončování a návrhů

Kombinace automatického dokončování a návrhů je nejsložitější z našich možností a pravděpodobně poskytuje nejlepší uživatelské prostředí. To, co chceme zobrazit, je první volba Azure Cognitive Search pro automatické dokončování textu. V rozevíracím seznamu chceme také celou řadu návrhů.

Existují knihovny, které tuto funkci nabízejí – často označované jako "vložené automatické dokončování" nebo podobný název. Tuto funkci ale budeme nativně implementovat, abyste mohli prozkoumat rozhraní API. V tomto příkladu začneme pracovat na kontroleru jako první.

  1. Přidejte do kontroleru akci, která vrátí jenom jeden výsledek automatického dokončování spolu se zadaným počtem návrhů. Tuto akci nazveme AutoCompleteAndSuggestAsync. Na domovském ovladači přidejte následující akci za další nové akce.

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

    V horní části seznamu výsledků se vrátí jedna možnost automatického dokončování následovaná všemi návrhy.

  2. V zobrazení nejprve implementujeme trik tak, aby se pod tučnější text zadaný uživatelem vykresloval světle šedé slovo automatického dokončování. HTML zahrnuje relativní umístění pro tento účel. Změňte příkaz TextBoxFor (a jeho okolní <příkazy div> ) na následující a nezapomeňte, že druhé vyhledávací pole identifikované jako pod ním je přímo pod naším normálním vyhledávacím polem tím, že toto vyhledávací pole vytáhnete o 39 pixelů od výchozího umístě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>
    

    Všimněte si, že v tomto případě znovu měníme ID na azureautocomplete .

  3. V zobrazení také po všech skriptech, které jste zatím zadali, zadejte následující skript. Skript je zdlouhavý a složitý kvůli různým chováním při zadávání, které zpracovává.

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

    Všimněte si, jak se funkce intervalu používá k vymazání podkladového textu, když už neodpovídá tomu, co uživatel píše, a také k nastavení stejných velkých a malých písmen (velká nebo malá), jak uživatel píše (protože "pa" při hledání odpovídá "PA", "pA", "Pa"), aby překryvný text byl čistý.

    Přečtěte si komentáře ve skriptu, abyste lépe porozuměli.

  4. Nakonec musíme provést menší úpravu dvou tříd HTML, aby byly průhledné. Přidejte následující řádek do tříd searchBoxForm a searchBox v souboru hotels.css.

    background: rgba(0,0,0,0);
    
  5. Teď aplikaci spusťte. Do vyhledávacího pole zadejte "pa". Dostanete "palác" jako návrh automatického dokončování, spolu se dvěma hotely, které obsahují "pa"?

    Psaní s automatickým dokončováním a návrhy vloženého textu

  6. Zkuste přijmout návrh automatického dokončování pomocí tabulátoru, zkuste vybrat návrhy pomocí kláves se šipkami a tabulátorem a zkuste to znovu pomocí myši a jednoho kliknutí. Ověřte, že skript zvládá všechny tyto situace úhledně.

    Možná se rozhodnete, že je jednodušší načíst knihovnu, která vám tuto funkci nabízí, ale teď znáte aspoň jeden způsob, jak automatické dokončování vloženého textu dovést do práce.

Shrnutí

Vezměte v úvahu následující poznatky z tohoto projektu:

  • Automatické dokončování (označované také jako "type-ahead") a návrhy můžou uživateli umožnit zadat jenom několik klíčů a najít přesně to, co chce.
  • Spolupráce automatického dokončování a návrhů může poskytovat bohaté uživatelské prostředí.
  • Funkce automatického dokončování vždy testujte se všemi formami vstupu.
  • Použití funkce setInterval může být užitečné při ověřování a opravách prvků uživatelského rozhraní.

Další kroky

V dalším kurzu se podíváme na další způsob, jak zlepšit uživatelské prostředí pomocí omezujících vlastností k zúžení hledání jediným kliknutím.