Oktatóanyag: Automatikus kiegészítés és javaslatok hozzáadása a .NET SDK használatával

Megtudhatja, hogyan valósíthatja meg az automatikus kiegészítést (gépeléses lekérdezések és javasolt eredmények), amikor a felhasználó elkezd begépelni egy keresőmezőbe. Ebben az oktatóanyagban az automatikusan összeállított lekérdezéseket és a javasolt eredményeket külön-külön, majd együtt jelenítjük meg. Előfordulhat, hogy egy felhasználónak csak két vagy három karaktert kell beírnia az összes elérhető eredmény megkereséséhez.

Eben az oktatóanyagban az alábbiakkal fog megismerkedni:

  • Javaslatok hozzáadása
  • Kiemelés hozzáadása a javaslatokhoz
  • Automatikus kiegészítés hozzáadása
  • Automatikus kiegészítés és javaslatok kombinálása

Áttekintés

Ez az oktatóanyag automatikus kiegészítést és javasolt eredményeket ad hozzá az előző Lapozás hozzáadása a keresési eredményekhez oktatóanyaghoz .

Az oktatóanyagban szereplő kód egy kész verziója a következő projektben található:

Előfeltételek

  • 2a-add-paging (GitHub) megoldás. Ez a projekt lehet az előző oktatóanyagból készült saját verzió, vagy a GitHubról származó másolat.

Javaslatok hozzáadása

Kezdjük azzal a legegyszerűbb esettel, amikor alternatív megoldásokat ajánlunk fel a felhasználónak: a javasolt eredmények legördülő listáját.

  1. Az index.cshtml fájlban módosítsa @id a TextBoxFor utasítást azureautosuggestre.

     @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautosuggest" }) <input value="" class="searchBoxSubmit" type="submit">
    
  2. Ezt az utasítást követve a /div> bezárása< után adja meg ezt a szkriptet. Ez a szkript a nyílt forráskódú jQuery felhasználói felületi kódtár automatikus kiegészítési vezérlőjével jeleníti meg a javasolt eredmények legördülő listáját.

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

    Az azonosító "azureautosuggest" csatlakoztatja a fenti szkriptet a keresőmezőhöz. A widget forrásbeállítása egy Javaslat metódusra van állítva, amely meghívja a Suggest API-t két lekérdezési paraméterrel: kiemelések és homályos, mindkettő hamis értékre van állítva ebben a példányban. Emellett legalább két karakterre van szükség a keresés elindításához.

JQuery-szkriptekre mutató hivatkozások hozzáadása a nézethez

  1. A jQuery-kódtár eléréséhez módosítsa a <nézetfájl fő> szakaszát a következő kódra:

    <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. Mivel új jQuery-hivatkozást vezetünk be, el kell távolítanunk vagy megjegyzést kell fűznünk az alapértelmezett jQuery-hivatkozáshoz a _Layout.cshtml fájlban (a Nézetek/Megosztott mappában). Keresse meg a következő sorokat, és tegye megjegyzésbe az első szkriptsort az ábrán látható módon. Ez a módosítás megakadályozza a jQueryre mutató hivatkozások összeütközését.

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

    Most már használhatjuk az előre definiált automatikus kiegészítési jQuery függvényeket.

A Javaslat művelet hozzáadása a vezérlőhöz

  1. Az otthoni vezérlőben adja hozzá a SuggestAsync műveletet (a PageAsync művelet után).

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

    A Méret paraméter megadja, hogy hány eredményt adjon vissza (ha nincs megadva, az alapértelmezett érték 5). Az index létrehozásakor egy javaslattevő van megadva a keresési indexen. A Microsoft által üzemeltetett minta szállodák indexében a javaslattevő neve "sg", és kizárólag a HotelName mezőben keres javasolt találatokat.

    A homályos egyeztetés lehetővé teszi, hogy a "közel hiányzók" szerepeljenek a kimenetben, akár egy szerkesztési távolságig. Ha a highlights paraméter igaz értékre van állítva, akkor félkövér HTML-címkék lesznek hozzáadva a kimenethez. Mindkét paramétert igaz értékre állítjuk a következő szakaszban.

  2. Előfordulhat, hogy szintaxishibák jelennek meg. Ha igen, adja hozzá az alábbi két utasítást a fájl tetejére.

    using System.Collections.Generic;
    using System.Linq;
    
  3. Futtassa az alkalmazást. Kap egy sor lehetőséget, amikor például a "po" kifejezést adja meg? Most próbálja ki a "pa" elemet.

    A *po* beírása két javaslatot jelenít meg

    Figyelje meg, hogy a beírt betűknek egy szót kell kezdenie, és nem kell egyszerűen belefoglalni a szóba.

  4. A nézetszkriptben állítsa &fuzzy értéket true (igaz) értékre, majd futtassa újra az alkalmazást. Most írja be a "po" szót. Figyelje meg, hogy a keresés feltételezi, hogy egy betű hibás.

    *pa* beírása igazra állított fuzzy beállítással

    Ha érdekli, az Azure Cognitive Search Lucene lekérdezési szintaxisa részletesen ismerteti a homályos keresésekben használt logikát.

Kiemelés hozzáadása a javaslatokhoz

A kiemelési paraméter igaz értékre állításával javíthatjuk a javaslatok megjelenését a felhasználó számára. Először azonban fel kell adnunk egy kódot a nézethez a félkövér szöveg megjelenítéséhez.

  1. A nézetben (index.cshtml) adja hozzá a következő szkriptet a "azureautosuggest" korábban ismertetett szkript után.

    <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. Most módosítsa a szövegdoboz azonosítóját, hogy az a következőképpen legyen olvasható.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azuresuggesthighlights" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. Futtassa újra az alkalmazást, és a javaslatokban félkövérre kell látnia a beírt szöveget. Próbálja meg beírni a "pa" szót.

    *pa* beírása kiemeléssel

    A fenti kiemelési szkriptben használt logika nem bolondbiztos. Ha olyan kifejezést ad meg, amely kétszer jelenik meg ugyanabban a névben, a félkövérrel jelölt eredmények nem egészen a kívántak. Próbálja meg beírni a "mo" szót.

    Az egyik kérdés, amire a fejlesztőnek válaszolnia kell, az az, hogy mikor működik "elég jól" egy szkript, és mikor kell foglalkoznia a quirks-ekkel. Ebben az oktatóanyagban nem emelünk ki további kiemeléseket, de a pontos algoritmus megkeresése megfontolandó, ha a kiemelés nem hatékony az adatok esetében. További információ: Találatok kiemelése.

Automatikus kiegészítés hozzáadása

A javaslatoktól kissé eltérő másik változat az automatikus kiegészítés (más néven "type-ahead"), amely befejez egy lekérdezési kifejezést. A felhasználói élmény javítása előtt ismét a legegyszerűbb implementációval kezdjük.

  1. Írja be a következő szkriptet a nézetbe a korábbi szkriptek követésével.

    <script>
        $("#azureautocompletebasic").autocomplete({
            source: "/Home/Autocomplete",
            minLength: 2,
            position: {
                my: "left top",
                at: "left-23 bottom+10"
            }
        });
    </script>
    
  2. Most módosítsa a szövegdoboz azonosítóját, hogy az a következőképpen legyen olvasható.

    @Html.TextBoxFor(m => m.searchText, new { @class = "searchBox", @id = "azureautocompletebasic" }) <input value="" class="searchBoxSubmit" type="submit">
    
  3. Az otthoni vezérlőben adja meg az AutocompleteAsync műveletet a SuggestAsync művelet után.

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

    Figyelje meg, hogy ugyanazt az "sg" nevű javaslattevő függvényt használjuk az automatikus kiegészítési keresésben, mint a javaslatokat (tehát csak a szállodanevek automatikus kiegészítését próbáljuk meg).

    Az AutocompleteMode beállítások egy sorát használjuk, és a OneTermWithContext parancsot használjuk. A további lehetőségek leírását az Automatikus kiegészítés API-ra hivatkozva hatja meg.

  4. Futtassa az alkalmazást. Figyelje meg, hogy a legördülő listában megjelenő lehetőségek tartománya egyetlen szó. Próbálkozzon a "re" betűvel kezdődő szavak beírásával. Figyelje meg, hogy a lehetőségek száma csökken, mivel több betű van beírva.

    Gépelés alapszintű automatikus kiegészítéssel

    Jelenleg a korábban futtatott javaslati szkript valószínűleg hasznosabb, mint ez az automatikus kiegészítési szkript. Az automatikus kiegészítés felhasználóbarátabbá tétele érdekében fontolja meg a javasolt eredmények használatát.

Automatikus kiegészítés és javaslatok kombinálása

Az automatikus kiegészítés és a javaslatok kombinálása a legösszetettebb lehetőség, és valószínűleg a legjobb felhasználói élményt nyújtja. Azt szeretnénk, hogy a beírt szöveggel beágyazott módon jelenítse meg az első Azure Cognitive Search a szöveg automatikus kiegészítéséhez. Emellett több javaslatot is szeretnénk legördülő listaként.

Vannak olyan kódtárak, amelyek ezt a funkciót kínálják – ezeket gyakran "beágyazott automatikus kiegészítésnek" vagy hasonló névnek nevezik. Ezt a funkciót azonban natív módon fogjuk implementálni, hogy megismerhesse az API-kat. Ebben a példában először a vezérlőn fogunk dolgozni.

  1. Adjon hozzá egy műveletet a vezérlőhöz, amely csak egy automatikus kiegészítési eredményt ad vissza, valamint egy megadott számú javaslatot. Ezt a műveletet Automatikus kiegészítésAndSuggestAsync néven fogjuk meghívni. Az otthoni vezérlőben adja hozzá a következő műveletet a többi új művelet követésével.

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

    Az eredménylista tetején egy automatikus kiegészítési lehetőség lesz visszaadva, amelyet az összes javaslat követ.

  2. A nézetben először implementálunk egy trükköt, hogy egy világosszürke automatikus kiegészítési szót jelenítsünk meg közvetlenül a felhasználó által beírt félkövérebb szöveg alatt. A HTML a relatív elhelyezést is magában foglalja erre a célra. Módosítsa a TextBoxFor utasítást (és annak környező <div> utasításait) a következőkre, és jegyezzük fel, hogy az alatta azonosított második keresőmező közvetlenül a normál keresőmező alatt található, és húzza ki ezt a keresőmezőt 39 képponttal az alapértelmezett helyéről!

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

    Figyelje meg, hogy ismét módosítjuk az azonosítót azureautocomplete-re ebben az esetben.

  3. A nézetben is írja be a következő szkriptet az eddig beírt szkriptek után. A szkript hosszadalmas és összetett, mivel számos bemeneti viselkedést kezel.

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

    Figyelje meg, hogy az intervallumfüggvény mind a mögöttes szöveg törlésére szolgál, ha már nem egyezik meg azzal, amit a felhasználó beír, és ugyanazt a kis- és nagybetűt (felső vagy alsó) állítja be, mint a felhasználó (mivel a "pa" megegyezik a "PA", a "pA", a "Pa" kifejezéssel a keresés során), hogy a felülírt szöveg rendezett legyen.

    A teljesebb megértés érdekében olvassa el a szkript megjegyzéseit.

  4. Végül egy kisebb módosítást kell hajtanunk végre két HTML-osztályon, hogy átláthatóvá tegyük őket. Adja hozzá a következő sort a searchBoxForm és a searchBox osztályokhoz a hotels.css fájlban.

    background: rgba(0,0,0,0);
    
  5. Most futtassa az alkalmazást. Írja be a "pa" kifejezést a keresőmezőbe. Kap "palota" az automatikus kiegészítési javaslat, valamint két hotel, amelyek tartalmazzák a "pa"?

    Gépelés beágyazott automatikus kiegészítéssel és javaslatokkal

  6. Próbáljon meg lapozással elfogadni az automatikus kiegészítési javaslatot, és a nyílbillentyűkkel és a tabulátorbillentyűvel válasszon javaslatokat, majd próbálkozzon újra az egérrel és egyetlen kattintással. Ellenőrizze, hogy a szkript megfelelően kezeli-e ezeket a helyzeteket.

    Dönthet úgy, hogy egyszerűbb betölteni egy olyan tárat, amely ezt a funkciót kínálja Önnek, de most már legalább egy módszert ismer a beágyazott automatikus kiegészítés működéséhez.

Legfontosabb ismeretek

Vegye figyelembe a projekt alábbi tanulságait:

  • Az automatikus kiegészítés (más néven "előre"), illetve a javaslatok lehetővé teszik, hogy a felhasználó csak néhány kulcsot írjon be, hogy pontosan azt keresse meg, amit szeretne.
  • Az automatikus kiegészítés és a közösen végzett javaslatok gazdag felhasználói élményt nyújthatnak.
  • Mindig tesztelje az automatikus kiegészítési függvényeket a bemenet minden formájával.
  • A setInterval függvény használata hasznos lehet a felhasználói felület elemeinek ellenőrzésében és javításában.

Következő lépések

A következő oktatóanyagban egy másik módszert mutatunk be a felhasználói élmény javítására, a aspektusok használatával egyetlen kattintással szűkítheti a kereséseket.