在客户端应用中添加自动完成和搜索建议

“键入时搜索”是提高查询效率的一种常用技术。 在 Azure AI 搜索中,此体验是通过“自动完成”支持的。自动完成可根据部分输入来完成某个字词或短语(使用“microsoft”来补全“micro”)。 另一种用户体验是“建议”或匹配文档的简短列表(返回具有某个 ID 的书名,以便可以链接到该书的详细信息页)。 自动完成和建议都是根据索引中的匹配项预测的。 服务不会提供返回零个结果的查询。

若要在 Azure AI 搜索中实现这些体验:

  • suggester 添加到索引架构。
  • 构建一个在请求中调用自动完成建议 API 的查询。
  • 添加一个用于在客户端应用中处理“边键入边搜索”交互的 UI 控件。 对于此目的,我们建议使用现有的 JavaScript 库。

在 Azure AI 搜索中,自动完成的查询和建议的结果是在搜索索引中从向建议器注册的选定字段中检索的。 建议器是索引的一部分,它指定哪些字段提供完成查询和/或建议结果的内容。 创建并加载索引后,将在内部创建建议器数据结构,以存储用于对部分查询进行匹配的前缀。 对于建议,选择唯一或者至少不重复的适当字段对于实现该体验至关重要。 有关详细信息,请参阅创建建议器

本文的剩余内容将重点介绍查询和客户端代码。 其中使用了 JavaScript 和 C# 来演示关键点。 使用了 REST API 示例来简要演示每个操作。 有关端到端代码示例,请参阅后续步骤

设置请求

请求的元素包括一个“边键入边搜索”API、一个部分查询和一个建议器。 以下脚本使用“自动完成 REST API”作为示例来演示请求的组成部分。

POST /indexes/myxboxgames/docs/autocomplete?search&api-version=2020-06-30
{
  "search": "minecraf",
  "suggesterName": "sg"
}

“suggesterName”提供建议器感知的字段,用以完成字词或建议。 具体对于建议而言,字段列表应该由那些在匹配结果之间中提供明确选择的字段构成。 在销售电脑游戏的站点上,该字段可能是游戏名称。

“search”参数提供了部分查询,其中的字符通过 jQuery 自动完成控件馈送到查询请求。 在上面的示例中,“minecraf”静态演示了控件可传入的内容。

API 不会对部分查询施加最小长度要求;查询长度可以短至一个字符。 但是,jQuery 自动完成提供了一个最小长度。 通常最少包含两到三个字符。

匹配项出现在输入字符串中任意位置的字词的开头。 假如输入字符串为“the quick brown fox”,则自动完成和建议均匹配部分字词“the”、“quick”、“brown”或“fox”,但不匹配字词中包含的部分字符,例如“rown”或“ox”。 此外,每次匹配都会设置下游扩展的范围。 部分查询“quick br”会匹配“quick brown”或“quick bread”,但“brown”或“bread”本身都不是匹配项,除非它们前面带有“quick”。

用于“边键入边搜索”的 API

请参考 REST 和 .NET SDK 参考页的以下链接:

构建响应

对自动完成和建议的响应是你可能对模式的期望:自动完成返回字词列表,建议返回字词加上文档 ID,以便你提取文档(使用查找文档 API 提取详细信息页的特定文档)。

响应格式由请求中的参数确定:

  • 对于自动完成,请设置 autocompleteMode 来确定是要对一个还是两个字词执行文本完成。

  • 对于建议,请设置 $select 以返回包含唯一值或区别性值(如名称和说明)的字段。 避免使用包含重复值(例如类别或城市)的字段。

以下参数适用于自动完成和建议,但更适用于建议(尤其是建议器包含多个字段的情况)。

参数 使用情况
searchFields 将查询限制为特定字段。
$filter 对结果集应用匹配条件 ($filter=Category eq 'ActionAdventure')。
$top 将结果限制为特定的数量 ($top=5)。

添加用户交互代码

自动填充查询字词或删除匹配链接的列表需要用户交互代码(通常为 JavaScript),这些代码可以使用来自外部源(例如,针对 Azure 搜索认知索引运行的自动完成或建议查询)的请求。

尽管你可以在本机编写此代码,但使用现有 JavaScript 库中的函数会比较简单,如下所示。

  • 建议代码片段中显示的自动完成小组件 (jQuery UI)。 你可以创建搜索框,然后在使用自动完成小组件的 JavaScript 函数中引用它。 该小组件中的属性设置源(自动完成或建议函数)、执行操作之前的输入字符的最小长度,以及位置。

  • 自动完成代码片段中显示的 XDSoft 自动完成插件

  • JavaScript 教程 和代码示例中显示的建议

使用客户端中的这些库来创建支持建议和自动完成的搜索框。 然后,在搜索框中收集的输入可以与搜索服务上的建议和自动完成操作配对。

建议

本部分逐步讲解建议的结果的一个实现,从搜索框定义开始。 此外,它还演示了如何使用脚本来调用本文中引用的第一个 JavaScript 自动完成库。

假设你有 jQuery UI Autocomplete 库并有一个以 C# 编写的 MVC 项目,则可以在 Index.cshtml 文件中使用 JavaScript 来定义搜索框。 该库通过异步调用 MVC 控制器来检索建议,将“边键入边搜索”交互添加到搜索框。

在 \Views\Home 文件夹下的 Index.cshtml 中,用于创建搜索框的代码行可能如下所示

<input class="searchBox" type="text" id="searchbox1" placeholder="search">

此示例是一个简单的输入文本框,包含用于设置样式的类、JavaScript 引用的 ID,以及占位符文本。

在同一文件中,嵌入引用搜索框的 JavaScript。 以下函数调用建议 API,该 API 根据部分字词输入来请求建议的匹配文档:

$(function () {
    $("#searchbox1").autocomplete({
        source: "/home/suggest?highlights=false&fuzzy=false&",
        minLength: 3,
        position: {
            my: "left top",
            at: "left-23 bottom+10"
        }
    });
});

source 告知 jQuery UI Autocomplete 函数要从何处获取显示在搜索框下的项列表。 由于此项目是一个 MVC 项目,因此它将调用 HomeController.cs 中的 Suggest 函数,该函数包含用于返回查询建议的逻辑。 此函数还会传递一些参数来控制突出显示内容、模糊匹配项和字词。 自动完成 JavaScript API 会添加字词参数。

minLength: 3 确保仅当搜索框中至少有三个字符时,才显示建议。

启用模糊匹配

使用模糊搜索可以根据接近的匹配项获取结果,即使用户在搜索框中拼错了单词。 编辑距离为 1,这意味着,用户输入与匹配项之间的最大差异只能是一个字符。

source: "/home/suggest?highlights=false&fuzzy=true&",

启用突出显示

突出显示将字体样式应用于结果中与输入对应的字符。 例如,如果部分输入为“micro”,则结果将显示为 microsoft、microscope 等。 突出显示基于 Suggestion 函数中内联定义的 HighlightPreTag 和 HighlightPostTag 参数。

source: "/home/suggest?highlights=true&fuzzy=true&",

Suggest 函数

如果使用 C# 和 MVC 应用程序,可以在 Controllers 目录下的 HomeController.cs 文件中为建议的结果创建类。 在 .NET 中,Suggest 函数基于 SuggestAsync 方法。 有关 .NET SDK 的详细信息,请参阅如何从 .NET 应用程序使用 Azure AI 搜索

InitSearch 方法为 Azure AI 搜索服务创建经过身份验证的 HTTP 索引客户端。 SuggestOptions 类的属性决定了要搜索并要在结果中返回的字段、匹配项的数量以及是否使用模糊匹配。

对于自动完成功能,模糊匹配限制为一个编辑距离(一个省略的或错误放置的字符)。 自动完成查询中的模糊匹配有时会产生意外的结果,具体取决于索引大小及其分片方式。 有关详细信息,请参阅分区和分片的概念

public async Task<ActionResult> SuggestAsync(bool highlights, bool fuzzy, string term)
{
    InitSearch();

    var options = new SuggestOptions()
    {
        UseFuzzyMatching = fuzzy,
        Size = 8,
    };

    if (highlights)
    {
        options.HighlightPreTag = "<b>";
        options.HighlightPostTag = "</b>";
    }

    // Only one suggester can be specified per index.
    // The suggester for the Hotels index enables autocomplete/suggestions on the HotelName field only.
    // During indexing, HotelNames are indexed in patterns that support autocomplete and suggested results.
    var suggestResult = await _searchClient.SuggestAsync<Hotel>(term, "sg", options).ConfigureAwait(false);

    // Convert the suggest 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);
}

SuggestAsync 函数采用两个参数,用于确定是返回命中突出显示,还是在搜索词输入的基础上使用模糊匹配。 建议的结果中最多可以包含 8 个匹配项。 该方法创建 SuggestOptions 对象,该对象随后会传递给 Suggest API。 然后,结果将转换成 JSON,以便在客户端中显示。

自动完成

到目前为止,搜索 UX 代码以建议为中心。 下一个代码块演示了如何使用 XDSoft jQuery UI Autocomplete 函数实现自动完成,该函数传入一个请求来实现 Azure AI 搜索自动完成。 与建议一样,在 C# 应用程序中,支持用户交互的代码位于 index.cshtml 中

$(function () {
    // using modified jQuery Autocomplete plugin v1.2.8 https://xdsoft.net/jqplugins/autocomplete/
    // $.autocomplete -> $.autocompleteInline
    $("#searchbox1").autocompleteInline({
        appendMethod: "replace",
        source: [
            function (text, add) {
                if (!text) {
                    return;
                }

                $.getJSON("/home/autocomplete?term=" + text, function (data) {
                    if (data && data.length > 0) {
                        currentSuggestion2 = data[0];
                        add(data);
                    }
                });
            }
        ]
    });

    // complete on TAB and clear on ESC
    $("#searchbox1").keydown(function (evt) {
        if (evt.keyCode === 9 /* TAB */ && currentSuggestion2) {
            $("#searchbox1").val(currentSuggestion2);
            return false;
        } else if (evt.keyCode === 27 /* ESC */) {
            currentSuggestion2 = "";
            $("#searchbox1").val("");
        }
    });
});

Autocomplete 函数

自动完成功能基于 AutocompleteAsync 方法。 与建议一样,此代码块位于 HomeController.cs 文件中

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

Autocomplete 函数采用搜索字词输入。 该方法创建 AutoCompleteParameters 对象。 然后,结果将转换成 JSON,以便在客户端中显示。

后续步骤

以下教程演示了“键入时搜索”体验。