Facet概述
Facet(直译为分面,实践来看可以叫做聚合)是由facet component支持的,将查询结果根据指定条件进行动态聚合,获得各类目信息的功能。
使用场景
最常见的一个例子是购物导航栏,如下图。在搜索“电脑”一词时,我们除了获得搜索结果,还会看到最上方的导航栏,它告诉我们关键词带有“电脑”的商品,分了几大类,每一类下面各有多少商品。
这就是facet功能的一个最基础的应用。这个好处是能引导用户逐步缩小搜索结果范围,最终找到自己想要的结果。
另一个场景是在筛选栏中替代传统的静态列表。如下图,选择行政区后,会下拉展开行政区下面的商圈。但与传统下拉列表不同的是,这里不会展示该区域下的所有商圈,只会展示有结果的商圈,避免用户的无效点击。这也是facet的功劳。
快速上手
想要在solr中使用这一功能,只需要简单的三步:
- 确认facetComponent加入请求处理链(SearchHandler默认有)
- 把要聚合的字段设置为可索引,或为此字段构建docValues正向索引
- 请求时增加facet=on&facet.field=field参数
将facetComponent加入请求处理链
Facet功能由facet组件提供支持,我们要确保在进行请求处理时能够调用这个组件。我们在solrconfig.xml中看到这样一段话:
<!-- Search Components
Search components are registered to SolrCore and used by
instances of SearchHandler (which can access them by name)
By default, the following components are available:
<searchComponent name="query" class="solr.QueryComponent" />
<searchComponent name="facet" class="solr.FacetComponent" />
<searchComponent name="highlight" class="solr.HighlightComponent" />
<searchComponent name="stats" class="solr.StatsComponent" />
<searchComponent name="debug" class="solr.DebugComponent" />
Default configuration in a requestHandler would look like:
<arr name="components">
<str>query</str>
<str>facet</str>
<str>mlt</str>
<str>highlight</str>
<str>stats</str>
<str>debug</str>
</arr>
-->
可见只要我们使用默认的searchHandler,而且不对component进行个性化设定,那么请求会被query、facet、mlt、highlight、stats、debug组件逐步处理。
如果使用自定义的Handler,或者覆写了componet列表,就需要注意加入facet component来支持聚合操作,否则该功能不生效。
字段索引
在前面筛选栏的例子,我们要知道哪些商圈有这个商品,假设商品的“商圈”字段名为commertial_district,那么需要indexd="true"或者docValues="true"。
如果对未索引的字段进行facet,则获得结果为空,但也不会报错。
小试牛刀
http://localhost:7070/solr/test/search?q=*:*&rows=0&facet=on&facet.field=prescription_type
这是最简单的使用,按指定字段值进行分组统计。可以看到除了docs之外,还返回了facet_count,所有和facet相关的结果都在这个key下。
Facet基础
常用参数
根据经验,以下参数能满足最基础的按值计数查询。
详情查询 Solr Ref Guide 6.6 Facet
参数 | 功能 | 默认值 |
---|---|---|
facet.field | 指定需要分面的字段 | |
facet.limit | 限制facet结果数目 | 100 |
facet.sort | 排序方式,可以是count(个数从高到低)或index(字典顺序) | count |
facet.mincount | facet 字段某值的计数小于此值,则不返回此值 | 0 |
facet.method | 指定使用的算法enum/fc/fcs/uif | fc |
facet.prefix | 指定字符串开头的词项来限制分面值,常用于自动补全功能 | |
facet.missing | 是否返回不含值的文档计数 | False |
facet query/range/interval
除了最常用的facet.field,在实际中还可能用到facet.query
,facet.range
,facet.interval
。
facet.query
- 使用facet.query灵活指定查询,统计符合指定查询的doc数。
- 可在同一查询中指定不同类型的facet query类型,如下图,一个为范围查询,一个为枚举查询。
- docs中的文档数仅受fq参数影响,facet.query不影响这里。
facet.range
如果说facet.query是最灵活的用法,那么facet.range则是为间距(gap)固定的范围查询量身定制的方法。下图中一目了然:
facet.interval
facet.range的缺憾是每个组的范围是一样的,不太灵活,facet.interval则弥补了这个不足。
- 使用小括号和中括号控制开闭区间
小Tips
- 对多值字段进行按值计数时,同一个doc中的不同值会分别计数一次,facet结果中各项之和可能会大于总doc数,这是正常的;
- 对分词类型字段进行按值统计时,会根据分词后的结果词来计算:
小结
facet只是查询中的一个环节,可讲的内容却不少,随便一写,文章也不短了。
作为基础,这一篇差不多够了,请期待下集!
参考
- 《solr in action》
- facet: https://lucene.apache.org/solr/guide/6_6/faceting.html