如何在 Azure 认知搜索中实现分面导航How to implement faceted navigation in Azure Cognitive Search

分面导航是一种筛选机制,用于在搜索应用程序中提供自定向的深化导航。Faceted navigation is a filtering mechanism that provides self-directed drilldown navigation in search applications. 术语“分面导航”可能让人觉得陌生,但我们以前也许用过它。The term 'faceted navigation' may be unfamiliar, but you've probably used it before. 如以下示例所示,分面导航就是用于筛选结果的类别。As the following example shows, faceted navigation is nothing more than the categories used to filter results.

Azure 认知搜索作业门户演示Azure Cognitive Search Job Portal Demo

分面导航是一个备用的搜索入口点。Faceted navigation is an alternative entry point to search. 它可以方便地替代手动键入复杂的搜索表达式。It offers a convenient alternative to typing complex search expressions by hand. 分面可帮助你查找所需的内容,同时确保获取相关结果。Facets can help you find what you're looking for, while ensuring that you don't get zero results. 作为开发人员,分面允许公开用于导航搜索索引的最有用的搜索条件。As a developer, facets let you expose the most useful search criteria for navigating your search index. 在线零售应用程序中,分面导航通常基于品牌、分类(童鞋)、尺寸、价格、受欢迎程度和评级生成。In online retail applications, faceted navigation is often built over brands, departments (kid's shoes), size, price, popularity, and ratings.

搜索技术不同,分面导航的实现也不同。Implementing faceted navigation differs across search technologies. 在 Azure 认知搜索中,分面导航在查询时生成,使用之前在架构中特性化的字段。In Azure Cognitive Search, faceted navigation is built at query time, using fields that you previously attributed in your schema.

  • 在应用程序生成的查询中,查询必须发送分面查询参数,才能获取该记录结果集的可用分面筛选值。In the queries that your application builds, a query must send facet query parameters to get the available facet filter values for that document result set.

  • 若要实际剪裁记录结果集,应用程序还必须应用 $filter 表达式。To actually trim the document result set, the application must also apply a $filter expression.

在应用程序开发中,编写构造查询的代码会产生大量工作。In your application development, writing code that constructs queries constitutes the bulk of the work. 想要从分面导航中获取的许多应用程序行为都由该服务提供,包括对定义范围操作和获取分面结果计数操作的内置支持。Many of the application behaviors that you would expect from faceted navigation are provided by the service, including built-in support for defining ranges and getting counts for facet results. 该服务还包括合理的默认值,有助于避免庞大的导航结构。The service also includes sensible defaults that help you avoid unwieldy navigation structures.

代码示例和演示Sample code and demo

本文使用作业搜索门户作为示例。This article uses a job search portal as an example. 该示例作为 ASP.NET MVC 应用程序实现。The example is implemented as an ASP.NET MVC application.

入门Get started

如果不熟悉搜索开发,对分面导航定义的最佳理解是它显示了自定向搜索的可能性。If you're new to search development, the best way to think of faceted navigation is that it shows the possibilities for self-directed search. 它是一种基于预定义筛选的深化搜索体验,用于通过点击操作快速缩小搜索结果范围。It's a type of drill-down search experience, based on predefined filters, used for quickly narrowing down search results through point-and-click actions.

交互模型Interaction model

分面导航的搜索体验是迭代的,因此我们可以首先将其理解为展开以响应用户操作的查询序列。The search experience for faceted navigation is iterative, so let's start by understanding it as a sequence of queries that unfold in response to user actions.

起始点是提供分面导航的应用程序页面,通常位于外围。The starting point is an application page that provides faceted navigation, typically placed on the periphery. 分面导航通常是树结构,带有每个值的复选框或可单击文本。Faceted navigation is often a tree structure, with checkboxes for each value, or clickable text.

  1. 发送到 Azure 认知搜索的查询通过一个或多个分面查询参数指定分面导航结构。A query sent to Azure Cognitive Search specifies the faceted navigation structure via one or more facet query parameters. 例如,查询可能包括 facet=Rating,可能通过 :values:sort 选项进一步优化表示。For instance, the query might include facet=Rating, perhaps with a :values or :sort option to further refine the presentation.
  2. 通过使用在请求中指定的分面,表示层可呈现提供分面导航的搜索页面。The presentation layer renders a search page that provides faceted navigation, using the facets specified on the request.
  3. 假设分面导航结构包括“评级”,单击“4”即表示仅应显示评级 4 或更高评级的产品。Given a faceted navigation structure that includes Rating, you click "4" to indicate that only products with a rating of 4 or higher should be shown.
  4. 作为响应,应用程序发送一个包括 $filter=Rating ge 4 的查询In response, the application sends a query that includes $filter=Rating ge 4
  5. 表示层会更新页面,显示减少的结果集,以便仅包含符合新筛选条件的项(在此示例中,是指评级为 4 或更高的产品)。The presentation layer updates the page, showing a reduced result set, containing just those items that satisfy the new criteria (in this case, products rated 4 and up).

分面是查询参数,不要将其与查询输入混淆。A facet is a query parameter, but do not confuse it with query input. 它绝不会用作查询中的选择条件。It is never used as selection criteria in a query. 相反,将分面查询参数视为对在响应中返回的导航结构的输入。Instead, think of facet query parameters as inputs to the navigation structure that comes back in the response. 对于提供的每个分面查询参数,Azure 认知搜索将评估每个分面值对应的部分结果中的记录数。For each facet query parameter you provide, Azure Cognitive Search evaluates how many documents are in the partial results for each facet value.

请注意步骤 4 中的 $filterNotice the $filter in step 4. 筛选器是分面导航的一个重要方面。The filter is an important aspect of faceted navigation. 尽管分面和筛选器在 API 中相互独立,但需要使用二者提供所需的体验。Although facets and filters are independent in the API, you need both to deliver the experience you intend.

应用设计模式App design pattern

在应用程序代码中,模式旨在使用分面查询参数返回分面导航结构以及分面结果,还可使用 $filter 表达式。In application code, the pattern is to use facet query parameters to return the faceted navigation structure along with facet results, plus a $filter expression. 筛选器表达式处理分面值的单击事件。The filter expression handles the click event on the facet value. $filter 表达式视为实际剪裁返回到表示层的搜索结果的代码隐藏。Think of the $filter expression as the code behind the actual trimming of search results returned to the presentation layer. 假设分面依据为“颜色”,通过 $filter 表达式单击颜色“红色”,表示仅选择颜色为红色的项。Given a Colors facet, clicking the color Red is implemented through a $filter expression that selects only those items that have a color of red.

查询基础知识Query basics

在 Azure 认知搜索中,通过一个或多个查询参数指定请求(有关每个参数的描述,请参阅搜索记录)。In Azure Cognitive Search, a request is specified through one or more query parameters (see Search Documents for a description of each one). 所有查询参数都不是必需的,但必须至少有一个查询参数,才能使查询有效。None of the query parameters are required, but you must have at least one in order for a query to be valid.

精度(表示能够筛选出不相关的匹配记录)通过以下一个或两个表达式实现:Precision, understood as the ability to filter out irrelevant hits, is achieved through one or both of these expressions:

  • search=search=
    此参数的值构成搜索表达式。The value of this parameter constitutes the search expression. 它可能是一段单独的文本,也可能是包含多个词语或运算符的复杂搜索表达式。It might be a single piece of text, or a complex search expression that includes multiple terms and operators. 在服务器上,搜索表达式用于全文搜索,在索引中查询可搜索字段获取匹配的词语,从而按排序顺序返回结果。On the server, a search expression is used for full-text search, querying searchable fields in the index for matching terms, returning results in rank order. 如果将 search 设置为 null,会在整个索引中执行查询(即 search=*)。If you set search to null, query execution is over the entire index (that is, search=*). 在此情况下,该查询的其他元素(例如 $filter 或计分配置文件)将是影响所返回文档 (($filter) 或所采用顺序(scoringProfile$orderby)的主要因素。In this case, other elements of the query, such as a $filter or scoring profile, are the primary factors affecting which documents are returned ($filter) and in what order (scoringProfile or $orderby).

  • $filter=$filter=
    筛选器是一种功能强大的机制,用于根据特定记录属性的值限制搜索结果的大小。A filter is a powerful mechanism for limiting the size of search results based on the values of specific document attributes. 先对 $filter 进行评估,然后针对生成可用值并对每个值进行相应计数的逻辑执行分面A $filter is evaluated first, followed by faceting logic that generates the available values and corresponding counts for each value

复杂搜索表达式会降低查询的性能。Complex search expressions decrease the performance of the query. 请尽可能使用合理结构化的筛选表达式提高精度并改进查询性能。Where possible, use well-constructed filter expressions to increase precision and improve query performance.

若要更好地了解筛选器如何添加更高精度,请比较复杂搜索表达式与包括筛选表达式的搜索表达式:To better understand how a filter adds more precision, compare a complex search expression to one that includes a filter expression:

  • GET /indexes/hotel/docs?search=lodging budget +Seattle –motel +parking
  • GET /indexes/hotel/docs?search=lodging&$filter=City eq 'Seattle' and Parking and Type ne 'motel'

这两个查询都有效,但如果要查找西雅图有停车场的非汽车旅馆,则第二个查询更好。Both queries are valid, but the second is superior if you're looking for non-motels with parking in Seattle.

  • 第一个查询依赖于提及的特定字词或字符串字段(如名称、描述)和包含可搜索数据的任何其他字段中未提及的字词。The first query relies on those specific words being mentioned or not mentioned in string fields like Name, Description, and any other field containing searchable data.
  • 第二个查询查找对结构化数据的精确匹配项,需要的准确性可能更高。The second query looks for precise matches on structured data and is likely to be much more accurate.

在包含分面导航的应用程序中,请确保缩小搜索结果范围来实现分面导航结果上的每个用户操作。In applications that include faceted navigation, make sure that each user action over a faceted navigation structure is accompanied by a narrowing of search results. 若要缩小结果范围,可使用筛选表达式。To narrow results, use a filter expression.

生成包含分面导航的应用Build a faceted navigation app

Azure 认知搜索中的分面导航在可生成搜索请求的应用程序代码中实现。You implement faceted navigation with Azure Cognitive Search in your application code that builds the search request. 分面导航依赖于前面定义的架构中的元素。The faceted navigation relies on elements in your schema that you defined previously.

Facetable [true|false] 索引属性在搜索索引中预定义,并在选定字段上设置以允许或拒绝在分面导航结构中使用。Predefined in your search index is the Facetable [true|false] index attribute, set on selected fields to enable or disable their use in a faceted navigation structure. 如果没有 "Facetable" = true,则无法在分面导航中使用字段。Without "Facetable" = true, a field cannot be used in facet navigation.

代码中的表示层提供用户体验。The presentation layer in your code provides the user experience. 它应列出分面导航的组成部分,例如标签、值、复选框和计数。It should list the constituent parts of the faceted navigation, such as the label, values, check boxes, and the count. Azure 认知搜索 REST API 与平台无关,因此可以使用所需的任何语言和平台。The Azure Cognitive Search REST API is platform agnostic, so use whatever language and platform you want. 请务必包括支持增量刷新的 UI 元素,以便在选择每个其他分面时更新 UI 状态。The important thing is to include UI elements that support incremental refresh, with updated UI state as each additional facet is selected.

在查询时,应用程序代码将创建包含 facet=[string] 的请求,该字符串是提供分面依据字段的请求参数。At query time, your application code creates a request that includes facet=[string], a request parameter that provides the field to facet by. 查询可能具有多个分面(例如 &facet=color&facet=category&facet=rating),每个分面采用与 (&) 字符分隔。A query can have multiple facets, such as &facet=color&facet=category&facet=rating, each one separated by an ampersand (&) character.

应用程序代码还必须构造 $filter 表达式,处理分面导航中的单击事件。Application code must also construct a $filter expression to handle the click events in faceted navigation. $filter 可减少搜索结果,使用分面值作为筛选条件。A $filter reduces the search results, using the facet value as filter criteria.

Azure 认知搜索根据输入的一个或多个词语返回搜索结果,以及对分面导航结构的更新。Azure Cognitive Search returns the search results, based on one or more terms that you enter, along with updates to the faceted navigation structure. 在 Azure 认知搜索中,分面导航是单级别构造,包含分面值以及针对每个值找到的结果计数。In Azure Cognitive Search, faceted navigation is a single-level construction, with facet values, and counts of how many results are found for each one.

以下部分详细介绍如何生成每个部分。In the following sections, we take a closer look at how to build each part.

生成索引Build the index

通过此索引属性,在索引中基于每个字段启用分面:"Facetable": trueFaceting is enabled on a field-by-field basis in the index, via this index attribute: "Facetable": true.
可能用于分面导航的所有字段类型在默认情况下均为 FacetableAll field types that could possibly be used in faceted navigation are Facetable by default. 此类字段类型包括 Edm.StringEdm.DateTimeOffset 和所有数值字段类型(实质上,所有字段类型都可进行分面,但 Edm.GeographyPoint 除外,因为它无法用于分面导航中)。Such field types include Edm.String, Edm.DateTimeOffset, and all the numeric field types (essentially, all field types are facetable except Edm.GeographyPoint, which can't be used in faceted navigation).

在生成索引时,分面导航的最佳做法是针对绝不应用作分面的字段显式关闭分面功能。When building an index, a best practice for faceted navigation is to explicitly turn faceting off for fields that should never be used as a facet. 具体而言,应将单独值的字符串字段(例如 ID 或产品名称)设置为 "Facetable": false,以避免在分面导航中意外(和无效)使用它们。In particular, string fields for singleton values, such as an ID or product name, should be set to "Facetable": false to prevent their accidental (and ineffective) use in faceted navigation. 在不需要分面的情况下将其关闭有助于保持较小的索引大小,通常可提高性能。Turning faceting off where you don't need it helps keep the size of the index small, and typically improves performance.

下面是作业门户演示示例应用的一部分架构,其中已剪裁某些属性,以减小大小:Following is part of the schema for the Job Portal Demo sample app, trimmed of some attributes to reduce the size:

{
  ...
  "name": "nycjobs",
  "fields": [
    { "name": "id",                 "type": "Edm.String",              "searchable": false, "filterable": false, ... "facetable": false, ... },
    { "name": "job_id",             "type": "Edm.String",              "searchable": false, "filterable": false, ... "facetable": false, ... },
    { "name": "agency",              "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "posting_type",        "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "num_of_positions",    "type": "Edm.Int32",              "searchable": false, "filterable": true, ...  "facetable": true, ...  },
    { "name": "business_title",      "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "civil_service_title", "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "title_code_no",       "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "level",               "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "salary_range_from",   "type": "Edm.Int32",              "searchable": false, "filterable": true, ...  "facetable": true, ...  },
    { "name": "salary_range_to",     "type": "Edm.Int32",              "searchable": false, "filterable": true, ...  "facetable": true, ...  },
    { "name": "salary_frequency",    "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
    { "name": "work_location",       "type": "Edm.String",             "searchable": true,  "filterable": true, ...  "facetable": true, ...  },
…
    { "name": "geo_location",        "type": "Edm.GeographyPoint",     "searchable": false, "filterable": true, ...  "facetable": false, ... },
    { "name": "tags",                "type": "Collection(Edm.String)", "searchable": true,  "filterable": true, ...  "facetable": true, ...  }
  ],
…
}

在示例架构中可以看到,对于不应该用作分面的字符串字段(例如 ID 值),Facetable 已关闭。As you can see in the sample schema, Facetable is turned off for string fields that shouldn't be used as facets, such as ID values. 在不需要分面的情况下将其关闭有助于保持较小的索引大小,通常可提高性能。Turning faceting off where you don't need it helps keep the size of the index small, and typically improves performance.

提示

作为最佳做法,包括每个字段的完整索引属性集。As a best practice, include the full set of index attributes for each field. 尽管 Facetable 对于几乎所有字段默认处于打开状态,但有意设置每个属性有助于深刻理解每个架构决策的含义。Although Facetable is on by default for almost all fields, purposely setting each attribute can help you think through the implications of each schema decision.

检查数据Check the data

数据质量直接影响分面导航结构是否按预期具体化。The quality of your data has a direct effect on whether the faceted navigation structure materializes as you expect it to. 它有助于构建可减少结果集的筛选器。It also affects the ease of constructing filters to reduce the result set.

如果希望按“品牌”或“价格”进行分面,每个记录都应包含 BrandNameProductPrice 值,这些值有效、一致且可用作筛选选项。If you want to facet by Brand or Price, each document should contain values for BrandName and ProductPrice that are valid, consistent, and productive as a filter option.

下面是要清理的内容的一些提醒:Here are a few reminders of what to scrub for:

  • 对于分面依据的每个字段,判断它包含的值是否适合作为自定向搜索中的筛选器。For every field that you want to facet by, ask yourself whether it contains values that are suitable as filters in self-directed search. 这些值应该简短、具有描述性且特点明显,以便用户在有竞争力的选项之间明确选择此值。The values should be short, descriptive, and sufficiently distinctive to offer a clear choice between competing options.
  • 拼写错误或几乎匹配的值。Misspellings or nearly matching values. 如果分面依据为“颜色”,并且字段值包括 Orange 和 Ornage(拼写错误),根据“颜色”字段的分面将选取二者。If you facet on Color, and field values include Orange and Ornage (a misspelling), a facet based on the Color field would pick up both.
  • 混合大小写文本也可能在分面导航中造成破坏,orange 和 Orange 会显示为两个不同的值。Mixed case text can also wreak havoc in faceted navigation, with orange and Orange appearing as two different values.
  • 相同值的单数和复数形式可能导致为每个值生成单独的分面。Single and plural versions of the same value can result in a separate facet for each.

可想而知,认真准备数据是生成有效分面导航的重要方面。As you can imagine, diligence in preparing the data is an essential aspect of effective faceted navigation.

生成 UIBuild the UI

通过表示层重新处理有助于发现可能错误的要求,并了解对搜索体验至关重要的功能。Working back from the presentation layer can help you uncover requirements that might be missed otherwise, and understand which capabilities are essential to the search experience.

在分面导航上,Web 或应用程序页面可显示分面导航结构、检测页面上的用户输入并插入更改的元素。In terms of faceted navigation, your web or application page displays the faceted navigation structure, detects user input on the page, and inserts the changed elements.

对于 Web 应用程序,AJAX 通常用于表示层中,因为它允许用户刷新增量更改。For web applications, AJAX is commonly used in the presentation layer because it allows you to refresh incremental changes. 也可以使用 ASP.NET MVC 或任何其他通过 HTTP 连接到 Azure 认知搜索服务的可视化平台。You could also use ASP.NET MVC or any other visualization platform that can connect to an Azure Cognitive Search service over HTTP. 本文中参考的示例应用程序 - Azure 认知搜索作业门户演示 - 正好是一个 ASP.NET MVC 应用程序。The sample application referenced throughout this article -- the Azure Cognitive Search Job Portal Demo – happens to be an ASP.NET MVC application.

在该示例中,分面导航内置于搜索结果页面中。In the sample, faceted navigation is built into the search results page. 源自示例应用程序的 index.cshtml 文件的以下示例显示了静态 HTML 结构,用于在搜索结果页面中显示分面导航。The following example, taken from the index.cshtml file of the sample application, shows the static HTML structure for displaying faceted navigation on the search results page. 提交搜索词或者选择或清除分面时,系统会动态生成或重新生成分面列表。The list of facets is built or rebuilt dynamically when you submit a search term, or select or clear a facet.

<div class="widget sidebar-widget jobs-filter-widget">
  <h5 class="widget-title">Filter Results</h5>
    <p id="filterReset"></p>
    <div class="widget-content">

      <h6 id="businessTitleFacetTitle">Business Title</h6>
      <ul class="filter-list" id="business_title_facets">
      </ul>

      <h6>Location</h6>
      <ul class="filter-list" id="posting_type_facets">
      </ul>

      <h6>Posting Type</h6>
      <ul class="filter-list" id="posting_type_facets"></ul>

      <h6>Minimum Salary</h6>
      <ul class="filter-list" id="salary_range_facets">
      </ul>

  </div>
</div>

源自 index.cshtml 页面的以下代码片段动态生成 HTML 来显示第一个分面“职称”。The following code snippet from the index.cshtml page dynamically builds the HTML to display the first facet, Business Title. 类似的函数可为其他分面动态生成 HTML。Similar functions dynamically build the HTML for the other facets. 每个方面具有标签和计数,用于显示为该分面结果找到的项数。Each facet has a label and a count, which displays the number of items found for that facet result.

function UpdateBusinessTitleFacets(data) {
  var facetResultsHTML = '';
  for (var i = 0; i < data.length; i++) {
    facetResultsHTML += '<li><a href="javascript:void(0)" onclick="ChooseBusinessTitleFacet(\'' + data[i].Value + '\');">' + data[i].Value + ' (' + data[i].Count + ')</span></a></li>';
  }

  $("#business_title_facets").html(facetResultsHTML);
}

提示

设计搜索结果页面时,请记住添加用于清除分面的机制。When you design the search results page, remember to add a mechanism for clearing facets. 如果使用复选框,可以轻松了解如何清除筛选器。If you add check boxes, you can easily see how to clear the filters. 对于其他布局,可能需要痕迹导航模式或其他创新方法。For other layouts, you might need a breadcrumb pattern or another creative approach. 例如,在作业搜索门户示例应用程序中,可以单击所选分面后面的 [X] 来清除分面。For example, in the Job Search Portal sample application, you can click the [X] after a selected facet to clear the facet.

生成查询Build the query

编写用于生成查询的代码应指定有效查询的所有部分,包括搜索表达式、分面、筛选器、计分配置文件,所有这些内容都用于明确表述请求。The code that you write for building queries should specify all parts of a valid query, including search expressions, facets, filters, scoring profiles– anything used to formulate a request. 在本部分中,我们将了解分面适用于查询的部分,以及将筛选器与分面结合使用来交付减少后的结果集的方式。In this section, we explore where facets fit into a query, and how filters are used with facets to deliver a reduced result set.

请注意,分面是此示例应用程序中不可或缺的部分。Notice that facets are integral in this sample application. 作业门户演示中的搜索体验围绕分面导航和筛选器进行设计。The search experience in the Job Portal Demo is designed around faceted navigation and filters. 页面上分面导航的突出位置展示了其重要性。The prominent placement of faceted navigation on the page demonstrates its importance.

通常,最好从示例着手。An example is often a good place to begin. 源自 JobsSearch.cs 文件的以下示例生成将基于“职称”、“工位”、“职位类型”和“最低薪水”创建分面导航的请求。The following example, taken from the JobsSearch.cs file, builds a request that creates facet navigation based on Business Title, Location, Posting Type, and Minimum Salary.

SearchParameters sp = new SearchParameters()
{
  ...
  // Add facets
  Facets = new List<String>() { "business_title", "posting_type", "level", "salary_range_from,interval:50000" },
};

分面查询参数设置为字段,根据数据类型,可通过逗号分隔列表(包括 count:<integer>sort:<>interval:<integer>values:<list>)对其执行进一步参数化。A facet query parameter is set to a field and depending on the data type, can be further parameterized by comma-delimited list that includes count:<integer>, sort:<>, interval:<integer>, and values:<list>. 设置范围时,数值数据支持值列表。A values list is supported for numeric data when setting up ranges. 有关使用情况详细信息,请参阅搜索记录(Azure 认知搜索 API)See Search Documents (Azure Cognitive Search API) for usage details.

通过分面,应用程序明确表述的请求还应生成筛选器,以便根据分面值选择缩小候选记录集。Along with facets, the request formulated by your application should also build filters to narrow down the set of candidate documents based on a facet value selection. 对于自行车商店,分面导航提供了就“有哪些颜色、制造商和类型的自行车”问题的线索,For a bike store, faceted navigation provides clues to questions like What colors, manufacturers, and types of bikes are available?. 同时筛选对“在此价格区间,具体有哪些红色的山地自行车”问题的答案。Filtering answers questions like Which exact bikes are red, mountain bikes, in this price range?. 单击“红色”指示应仅显示红色产品时,应用程序发送的下一条查询将为 $filter=Color eq 'Red'When you click "Red" to indicate that only Red products should be shown, the next query the application sends includes $filter=Color eq 'Red'.

如果从“职称”分面中选择一个值,源自 JobsSearch.cs 页面的以下代码片段会将选定的职称添加到筛选器。The following code snippet from the JobsSearch.cs page adds the selected Business Title to the filter if you select a value from the Business Title facet.

if (businessTitleFacet != "")
  filter = "business_title eq '" + businessTitleFacet + "'";

提示和最佳实践Tips and best practices

索引编制提示Indexing tips

如果不使用搜索框,请提高索引效率Improve index efficiency if you don't use a Search box

如果应用程序以独占方式(即无搜索框)使用分面导航,可将字段标记为 searchable=falsefacetable=true 以生成更简洁的索引。If your application uses faceted navigation exclusively (that is, no search box), you can mark the field as searchable=false, facetable=true to produce a more compact index. 此外,仅在整个分面值上编制索引,不支持词内换行,也不支持对包含多个词的值的组成部分编制索引。In addition, indexing occurs only on whole facet values, with no word-break or indexing of the component parts of a multi-word value.

指定哪些字段可用作分面Specify which fields can be used as facets

回想一下,索引的架构确定哪些字段可用作分面。Recall that the schema of the index determines which fields are available to use as a facet. 假设某个字段可进行分面,该查询可指定分面依据的字段。Assuming a field is facetable, the query specifies which fields to facet by. 分面时依据的字段提供了显示在标签下面的值。The field by which you are faceting provides the values that appear below the label.

显示在每个标签下面的值可从索引检索。The values that appear under each label are retrieved from the index. 例如,如果分面字段为“颜色”,可用于其他筛选的值将是该字段的值(红色、黑色等)。For example, if the facet field is Color, the values available for additional filtering are the values for that field - Red, Black, and so forth.

仅可针对 Numeric 和 DateTime 值,在分面字段上显式设置值(例如 facet=Rating,values:1|2|3|4|5)。For Numeric and DateTime values only, you can explicitly set values on the facet field (for example, facet=Rating,values:1|2|3|4|5). 这些字段类型允许使用值列表,以简化将分面结果分入连续范围(基于数值或时段的范围)操作。A values list is allowed for these field types to simplify the separation of facet results into contiguous ranges (either ranges based on numeric values or time periods).

默认情况下,只能具有单个层次的分面导航By default you can only have one level of faceted navigation

如上所述,不存在对在层次结构中嵌套分面的直接支持。As noted, there is no direct support for nesting facets in a hierarchy. 默认情况下,Azure 认知搜索中的分面导航仅支持一个筛选器级别。By default, faceted navigation in Azure Cognitive Search only supports one level of filters. 但是,存在解决方法。However, workarounds do exist. 可以针对每个层次结构使用一个入口点,在 Collection(Edm.String) 中对层次结构分面结构进行编码。You can encode a hierarchical facet structure in a Collection(Edm.String) with one entry point per hierarchy. 本文未介绍如何实现此解决方法。Implementing this workaround is beyond the scope of this article.

查询提示Querying tips

验证字段Validate fields

如果根据不受信任的用户输入动态生成分面列表,应验证分面字段的名称是否有效。If you build the list of facets dynamically based on untrusted user input, validate that the names of the faceted fields are valid. 或者,在使用 .NET 中的 Uri.EscapeDataString() 或所选平台的等效项生成 URL 时会名称转义。Or, escape the names when building URLs by using either Uri.EscapeDataString() in .NET, or the equivalent in your platform of choice.

筛选提示Filtering tips

使用筛选器提高搜索准确性Increase search precision with filters

使用筛选器。Use filters. 如果只依赖于搜索表达式,词干分析可能导致返回的记录在其任何字段中都没有精度分面值。If you rely on just search expressions alone, stemming could cause a document to be returned that doesn't have the precise facet value in any of its fields.

使用筛选器提高搜索性能Increase search performance with filters

筛选器缩小搜索的候选记录集,并且不对它们进行排序。Filters narrow down the set of candidate documents for search and exclude them from ranking. 如果有大量的文档,使用选择性分面深化通常能够提高性能。If you have a large set of documents, using a selective facet drill-down often gives you better performance.

仅筛选分面字段Filter only the faceted fields

在分面深化时,通常只要在特定(分面)字段中,而不是在所有可搜索字段中的任意位置包括具有分面值的记录。In faceted drill-down, you typically want to only include documents that have the facet value in a specific (faceted) field, not anywhere across all searchable fields. 添加筛选器可增强目标字段,方法是将服务定向到仅在分面字段中搜索匹配的值。Adding a filter reinforces the target field by directing the service to search only in the faceted field for a matching value.

使用更多筛选器修剪分面结果Trim facet results with more filters

分面结果是在匹配分面词语的搜索结果中找到的记录。Facet results are documents found in the search results that match a facet term. 在以下示例中,在云计算的搜索结果中,254 个项还具有内部规范作为内容类型。In the following example, in search results for cloud computing, 254 items also have internal specification as a content type. 项不一定互相排斥。Items are not necessarily mutually exclusive. 如果某个项满足这两个筛选条件,它将分别计入每一个。If an item meets the criteria of both filters, it is counted in each one. 针对通常用于实现记录标记的 Collection(Edm.String) 字段进行分面时,可能会出现这种重复。This duplication is possible when faceting on Collection(Edm.String) fields, which are often used to implement document tagging.

    Search term: "cloud computing"
    Content type
       Internal specification (254)
       Video (10) 

一般情况下,如果发现分面结果持续很大,我们建议添加更多筛选器,以便为用户提供更多缩小搜索范围的选项。In general, if you find that facet results are consistently too large, we recommend that you add more filters to give users more options for narrowing the search.

关于结果计数的提示Tips about result count

限制分面导航中的项数Limit the number of items in the facet navigation

对于导航树中的每个分面字段,默认限制为 10 个值。For each faceted field in the navigation tree, there is a default limit of 10 values. 此默认值对导航结构有意义,因为它可使值列表保持在合理的大小。This default makes sense for navigation structures because it keeps the values list to a manageable size. 可通过向计数分配某个值替代默认值。You can override the default by assigning a value to count.

  • &facet=city,count:5 指定仅返回在排序最高的结果中找到的前五个城市作为分面结果。&facet=city,count:5 specifies that only the first five cities found in the top ranked results are returned as a facet result. 假设包含搜索词“机场”的示例查询有 32 个匹配项。Consider a sample query with a search term of "airport" and 32 matches. 如果查询指定 &facet=city,count:5,分面结果中仅包含前五个搜索结果中具有最多文档的唯一城市。If the query specifies &facet=city,count:5, only the first five unique cities with the most documents in the search results are included in the facet results.

请注意分面结果和搜索结果之间的区别。Notice the distinction between facet results and search results. 搜索结果是与查询匹配的所有记录。Search results are all the documents that match the query. 分面结果是与每个分面值对应的匹配项。Facet results are the matches for each facet value. 在该示例中,搜索结果将包括未在分面分类列表中的城市名称(在我们的示例中为 5)。In the example, search results include City names that are not in the facet classification list (5 in our example). 清理分面或选择“城市”以外的其他分面时,可以看到分面导航筛选出的结果。Results that are filtered out through faceted navigation become visible when you clear facets, or choose other facets besides City.

备注

讨论 count 时,如果存在多个类型,会让人产生混淆。Discussing count when there is more than one type can be confusing. 下表简要概述了在 Azure 认知搜索 API、示例代码和记录中使用词语的方式。The following table offers a brief summary of how the term is used in Azure Cognitive Search API, sample code, and documentation.

  • @colorFacet.count
    在表示代码中,应该在分面上看到一个计数参数,用于显示分面结果数。In presentation code, you should see a count parameter on the facet, used to display the number of facet results. 在分面结果中,计数指示与分面词语或范围匹配的记录数。In facet results, count indicates the number of documents that match on the facet term or range.
  • &facet=City,count:12
    在分面查询中,可将计数设置为某个值。In a facet query, you can set count to a value. 默认值为 10,但可以设置更高或更低的值。The default is 10, but you can set it higher or lower. 设置 count:12 可获取分面结果中按记录计数排序的前 12 个匹配项。Setting count:12 gets the top 12 matches in facet results by document count.
  • "@odata.count""@odata.count"
    在查询响应中,该值指示搜索结果中匹配项的数目。In the query response, this value indicates the number of matching items in the search results. 一般情况下,该值大于所有合并的分面结果总和,因为存在匹配搜索词但没有分面值匹配结果的项。On average, it's larger than the sum of all facet results combined, due to the presence of items that match the search term, but have no facet value matches.

获取分面结果中的计数Get counts in facet results

当向分面查询添加筛选器时,你可能希望保留分面语句(例如 facet=Rating&$filter=Rating ge 4)。When you add a filter to a faceted query, you might want to retain the facet statement (for example, facet=Rating&$filter=Rating ge 4). 从技术上讲,不需要分面“分级”,但保留它会返回分级 4 和更高分级的分面值计数。Technically, facet=Rating isn't needed, but keeping it returns the counts of facet values for ratings 4 and higher. 例如,如果单击“4”并且查询包括大于或等于“4”的筛选器,将针对每个等于和大于 4 的分级返回计数。For example, if you click "4" and the query includes a filter for greater or equal to "4", counts are returned for each rating that is 4 and higher.

确保获取准确的分面计数Make sure you get accurate facet counts

在某些情况下,可能发现分面计数与结果集不匹配(请参阅 Azure 认知搜索中的分面导航(论坛帖子))。Under certain circumstances, you might find that facet counts do not match the result sets (see Faceted navigation in Azure Cognitive Search (forum post)).

由于分片体系结构,分面计数可能不准确。Facet counts can be inaccurate due to the sharding architecture. 每个搜索索引具有多个分片,每个分片报告按记录计数排序的前 N 个分面,并合并到单个结果中。Every search index has multiple shards, and each shard reports the top N facets by document count, which is then combined into a single result. 如果某些分片具有大量匹配值,而其他分片的值很少,你可能会发现某些分面值丢失或未计入结果中。If some shards have many matching values, while others have fewer, you may find that some facet values are missing or under-counted in the results.

尽管此行为可能随时更改,但如果现在遇到此行为,可通过以下方式解决它:人为地将 count:<number> 扩大到较大的值,以强制从每个分片进行完整报告。Although this behavior could change at any time, if you encounter this behavior today, you can work around it by artificially inflating the count:<number> to a large number to enforce full reporting from each shard. 如果 count: 的值大于或等于字段中唯一值的数目,可保证获得准确结果。If the value of count: is greater than or equal to the number of unique values in the field, you are guaranteed accurate results. 但是,如果记录计数较高,性能可能会受到负面影响,因此请谨慎使用此选项。However, when document counts are high, there is a performance penalty, so use this option judiciously.

用户界面提示User interface tips

为分面导航中的每个字段添加标签Add labels for each field in facet navigation

标签通常在 HTML 或窗体(在示例应用程序中为 index.cshtml)中定义。Labels are typically defined in the HTML or form (index.cshtml in the sample application). Azure 认知搜索中没有用于分面导航标签或任何其他元数据的 API。There is no API in Azure Cognitive Search for facet navigation labels or any other metadata.

基于范围进行筛选Filter based on a range

基于值的范围分面是常见的搜索应用程序要求。Faceting over ranges of values is a common search application requirement. 数值数据和 DateTime 值都支持范围。Ranges are supported for numeric data and DateTime values. 可在搜索记录(Azure 认知搜索 API)中阅读有关每种方法的详细信息。You can read more about each approach in Search Documents (Azure Cognitive Search API).

Azure 认知搜索通过提供两种用于计算范围的方法,简化范围构造。Azure Cognitive Search simplifies range construction by providing two approaches for computing a range. 对于这两种方法,Azure 认知搜索根据用户提供的输入创建适当的范围。For both approaches, Azure Cognitive Search creates the appropriate ranges given the inputs you've provided. 例如,如果用户指定范围值为 10|20|30,它会自动创建范围 0-10、10-20、20-30。For instance, if you specify range values of 10|20|30, it automatically creates ranges of 0-10, 10-20, 20-30. 应用程序可以选择性地删除任何空间隔。Your application can optionally remove any intervals that are empty.

方法 1:使用间隔参数Approach 1: Use the interval parameter
要以 10 美元的增量设置价格分面,将指定:&facet=price,interval:10To set price facets in $10 increments, you would specify: &facet=price,interval:10

方法 2:使用值列表Approach 2: Use a values list
对于数值数据,可以使用值列表。For numeric data, you can use a values list. 考虑 listPrice 字段的分面范围,如下所示:Consider the facet range for a listPrice field, rendered as follows:

示例值列表Sample values list

若要根据上面的屏幕截图中所示指定分面范围,请使用值列表:To specify a facet range like the one in the preceding screenshot, use a values list:

facet=listPrice,values:10|25|100|500|1000|2500

通过以下方式生成每个范围:使用 0 作为起点、使用列表中的某个值作为终结点,并剪裁上一个范围以创建离散间隔。Each range is built using 0 as a starting point, a value from the list as an endpoint, and then trimmed of the previous range to create discrete intervals. Azure 认知搜索将执行这些操作作为分面导航的一部分。Azure Cognitive Search does these things as part of faceted navigation. 无需编写用于结构化每个间隔的代码。You do not have to write code for structuring each interval.

针对范围生成筛选器Build a filter for a range

若要根据所选的范围筛选文档,可以在包含两个部分的表达式中使用 "ge""lt" 筛选器运算符,该表达式可定义范围的终结点。To filter documents based on a range you select, you can use the "ge" and "lt" filter operators in a two-part expression that defines the endpoints of the range. 例如,如果为 listPrice 字段选择范围 10-25,筛选器将为 $filter=listPrice ge 10 and listPrice lt 25For example, if you choose the range 10-25 for a listPrice field, the filter would be $filter=listPrice ge 10 and listPrice lt 25. 在示例代码中,筛选器表达式使用 priceFrompriceTo 参数设置终结点。In the sample code, the filter expression uses priceFrom and priceTo parameters to set the endpoints.

查询值的范围Query for a range of values

基于距离进行筛选Filter based on distance

常见的筛选器用于根据你所在的当前位置帮助你选择附近的商店、餐馆或目的地。It's common to see filters that help you choose a store, restaurant, or destination based on its proximity to your current location. 虽然此类型的筛选器看起来像分面导航,但它只是一个筛选器。While this type of filter might look like faceted navigation, it's just a filter. 我们在此处针对专门查找该特定设计问题的实现建议的用户进行介绍。We mention it here for those of you who are specifically looking for implementation advice for that particular design problem.

Azure 认知搜索中有两个地理空间函数:geo.distancegeo.intersectsThere are two Geospatial functions in Azure Cognitive Search, geo.distance and geo.intersects.

  • geo.distance 函数返回两点之间的距离(以千米为单位)。The geo.distance function returns the distance in kilometers between two points. 一个点是字段,另一个点是作为筛选器一部分传递的常量。One point is a field and other is a constant passed as part of the filter.
  • 如果给定的点位于给定的多边形范围内,geo.intersects 函数将返回 true。The geo.intersects function returns true if a given point is within a given polygon. 该点是字段,多边形指定为作为筛选器一部分传递的坐标常量列表。The point is a field and the polygon is specified as a constant list of coordinates passed as part of the filter.

可以在 OData 表达式语法(Azure 认知搜索)中查找筛选器示例。You can find filter examples in OData expression syntax (Azure Cognitive Search).

尝试演示Try the demo

Azure 认知搜索作业门户演示包含本文中参考的示例。The Azure Cognitive Search Job Portal Demo contains the examples referenced in this article.

处理搜索结果时,观看“查询构造中的更改”的 URL。As you work with search results, watch the URL for changes in query construction. 此应用程序在选择每个分面时,将分面追加到 URI。This application happens to append facets to the URI as you select each one.

  1. 若要使用该演示应用的地图功能,请从必应地图开发人员中心获取必应地图密钥。To use the mapping functionality of the demo app, get a Bing Maps key from the Bing Maps Dev Center. 请粘贴该密钥并覆盖 index.cshtml 页面中的现有密钥。Paste it over the existing key in the index.cshtml page. 不使用 Web.config 文件中的 BingApiKey 设置。The BingApiKey setting in the Web.config file is not used.

  2. 运行应用程序。Run the application. 学习可选的教程,或关闭该对话框。Take the optional tour, or dismiss the dialog box.

  3. 输入搜索词(例如“分析师”),并单击“搜索”图标。Enter a search term, such as "analyst", and click the Search icon. 快速执行查询。The query executes quickly.

    分面导航结构也与搜索结果一起返回。A faceted navigation structure is also returned with the search results. 在搜索结果页面中,分面导航结构包括每个分面结果的计数。In the search result page, the faceted navigation structure includes counts for each facet result. 未选择任何分面,因此将返回所有匹配的结果。No facets are selected, so all matching results are returned.

    在选择分面之前搜索结果Search results before selecting facets

  4. 单击某个职称、工位或最低薪水。Click a Business Title, Location, or Minimum Salary. 分面在初始搜索时为 null,但当对它们设置值时,将从搜索结果中剪裁掉不再匹配的项。Facets were null on the initial search, but as they take on values, the search results are trimmed of items that no longer match.

    在选择分面之后搜索结果Search results after selecting facets

  5. 若要清除分面查询以便可以尝试不同的查询行为,请单击所选分面后面的 [X] 来清除分面。To clear the faceted query so that you can try different query behaviors, click the [X] after the selected facets to clear the facets.

了解详细信息Learn more

有关分面导航设计准则的更多见解,建议查看以下链接:For more insights on design principles for faceted navigation, we recommend the following links: