1.简述
1.1 概念
分面搜索也称为分面浏览,他允许用户在执行搜索时,根据文档的一个或者多个方面(即分面)对搜索结果进行细分。用户通过选择不同的过滤器来探索搜索结果。
1.2 应用场景
在搜索求职网站时,我们希望对搜索结果按照城市、工作类别、行业甚至是公司名称等选项进行筛选。一般来说,这些过滤选项不仅展示了每个分面的可用值,而且统计了每个分面值匹配到的搜索结果数。由于屏幕只能为每个分面显示有限数量的值,搜索引擎通常会根据热门程度(文档匹配最多的)对分面值进行排序。让用户无需查看每个搜索结果,就可以快速的搜索结果的整体情况。
1.3 功能
solr的分面功能将动态元数据随搜索结果一起返回。分面最基本的形式是展示字段中的每一个唯一值和其对匹配的文档出现的次数(注意:不是匹配的文档数量而是匹配的文档出现次数),这个字段来自文档的共享属性,例如:类目列表。
solr提供了许多高级分面功能,包括基于函数、值区间以及任意查询的搜索结果分面。solr还支持层级分面,多维分面与多选分面,其中多选分面可以对那些以及从搜索结果中过滤掉的文档进行分面计数。
2.搜索结果预览
分面搜索一般有两个步骤组成:分面的计算与显示,即“分面返回”,有时简称为分面;用户选择一个或者多个分面值,对搜索结果进行过滤,即“分面选择“或者”分面过滤“
假设对一组参观文档进行搜索,你可能希望在用户界面放置一些分面来作为导航元素,如下图,当查询”hamburger“时返回的结果:
如上图,每个类别(餐厅类型、州、价格区间及城市)都被视为一个分面。分面可以看成是对搜索结果的一个信息切片。这个界面类似于我们在购物网站搜索某一件商品后,然后根据商品的各种属性进行进一步的筛选。
3.字段分面
字段分面是最常见的分面形式。执行搜索时,根据查询请求返回特定字段中找到唯一值以及找到文档数。字段分面包括:单值分面和多值分面 。其中单值分面中每个唯一值都会被检视,并返回每个值对应的文档数,由于每个文档只需要一个值,因此此值的统计数等同于文档总数。多值分面中,多个标签可能对应同一个文档,因此大多数文档被不止一个分面值计数过。
对于多值分面,Solr开发者创建了一个单独的字段,在该字段中放入特定内容的副本,该字段仅用于分面目的,这样原始文本就能够以分面的形式保留。
3.1 字段分面参数
Solr参数 | 可能取值 | 说明 |
---|---|---|
facet | true,false | 对当前搜索是否启用分面 |
facet.field | 任意索引字段名称 | 确定对那个字段进行分面,可多次指定 |
facet.sort | index,count | 排序方式:根据最大出现次数(count)或者索引(index)的词典序排序 |
facet.limit | 整数>=-1 | 返回多少个唯一分面值 |
facet.mincount | 整数>=0 | 在分面返回之前设置必须出现最少文档数,默认为1. |
facet.method | enum,fc,fcs | enum方法循环遍历索引中所有词项,计算这些词项与查询的交集,fc(字段缓存)方法对与查询匹配的文档进行循环,在这些文档中找到词项,fc是除了布尔值之外的默认方法。fcs方法为单值字符串调用每个片段缓存。 |
facet.enum.cache.minDf | 整数>=0 | 在filterCache用于词项之前,指定与盖茨匹配的最小文档数 |
facet.prefix | 任意字符串 | 指定查询到词项的前缀 |
facet.missing | true,false | 是否返回不包含分面字段的文档计数 |
facet.offset | 整数>=0 | 通过分面值进行分页。offset指定跳过最开始的几个值,昨晚后面分面的替代 |
facet.threads | 整数 | 当执行多个字段分面时指定的线程数。默认是0,负数代表为每个字段生成一个线程 |
其中,可以基于字段进行指定的有:facet.limit,facet.mincount,facet.method,facet.enum.cache.minDf,使用格式为: f..= eg:
requestUrl:
http://192.168.10.125:8983/solr/techproducts/select?q=*:*&facet=true& // 开启facetfacet.limit=6& // 默认所有facet展示六条数据facet.field=weight& // facet字段为weightf.weight.facet.limit=4& // 指定weight字段只显示4条f.weight.facet.sort=index& // 指定weight字段为字典序排序facet.field=cat& f.cat.facet.mincount=2 // 最少统计数为2
response:
"facet_counts":{ "facet_queries":{}, "facet_fields":{ "weight":[ "2.0",1, "4.0",1, "5.5",1, "6.4",1], "cat":[ "electronics",12, "currency",4, "memory",3, "connector",2, "graphics card",2, "hard drive",2]}, "facet_ranges":{}, "facet_intervals":{}, "facet_heatmaps":{}}}
如结果所示:weight排序方式为字典序,cat排序方式为默认的count,即按照统计数量大小降序;weight展示了4条记录,cat未特殊指定数量,展示了默认的6条数据;cat指定最少统计数为2,weight未指定所以也展示出了为1的。
4. 查询分面
将某一个字段的值分为多个区间,查询每个区间对应的数量。例如,我们想知道商品在区间[,200]、[200,400]、[400,600]、[600,]中,每个区间对应的数量,则可以使用查询分面。格式为:facet.query=field:[start+TO+end],其中"["代表闭区间,"{"代表开区间,"+"代表空格,注意"TO"必须为大写。
http://192.168.10.125:8983/solr/techproducts/select?q=*:*&rows=0&facet=true&facet.query=price:[*+TO+200}&facet.query=price:[200+TO+400}&facet.query=price:[400+TO+600}&facet.query=price:[600+TO+*]
"facet_counts":{ "facet_queries":{ "price:[* TO 200}":9, "price:[200 TO 400}":4, "price:[400 TO 600}":1, "price:[600 TO *]":2}, "facet_fields":{}, "facet_ranges":{}, "facet_intervals":{}, "facet_heatmaps":{}}}
5.区间分面
区间分面将数值和日期字段分成一些区间,以便于solr返回各个区间以及他们包含的文档数。创建多个不同的查询分面来表示多个区间值的做法可以通过区间分面进行替代。
对上面的例子可通过以下方式实现:
http://192.168.10.125:8983/solr/techproducts/select?q=*:*&rows=0&facet=true&facet.range=price& // 分区字段f.price.facet.range.start=0.0& // 分区起始值f.price.facet.range.end=1000.0& // 分区结束值f.price.facet.range.gap=200 // 分区步长
可得到同样的统计结果
"facet_counts":{ "facet_queries":{}, "facet_fields":{}, "facet_ranges":{ "price":{ "counts":[ "0.0",9, "200.0",4, "400.0",1, "600.0",1, "800.0",0], "gap":200.0, "start":0.0, "end":1000.0}}, "facet_intervals":{}, "facet_heatmaps":{}}}
6.Pivot(Decision Tree)Faceting 决策树分面
通过pivot关键字定义树状结构的分面结果,在一个分面结果中可以包含另一个分面结果
http://localhost:8983/solr/techproducts/select?q=*:*&facet.pivot=cat,popularity,inStock&facet.pivot=popularity,cat&facet=true&facet.field=cat&facet.limit=5&rows=0&facet.pivot.mincount=2
分面结果:
{ "facet_counts":{ "facet_queries":{}, "facet_fields":{ "cat":[ "electronics",14, "currency",4, "memory",3, "connector",2, "graphics card",2]}, "facet_dates":{}, "facet_ranges":{}, "facet_pivot":{ "cat,popularity,inStock":[{ "field":"cat", "value":"electronics", "count":14, "pivot":[{ "field":"popularity", "value":6, "count":5, "pivot":[{ "field":"inStock", "value":true, "count":5}]}]}]}}}
7.其他
- 可在分面值查询请求上添加过滤器,例如
&fq=price:[*+TO100]
,将过滤掉对[0,100]的统计. - 多值过滤时需要使用双引号,例如
fq=city:"china beijing"
,如果字符串中有特殊符号需要进行转意,例如:fq=name:"the \"in\" crowd"
. - 通过key关键字给分面字段重命名,例如
facet.query={!key="两百以下"}price :[*+TO+200]
,则facet_query中的显示结果将由"price:[* TO 200}":9,
变为"price:[两百以下}":9,
- 通过tag和ex标记忽略过滤器。用tag定义一个过滤器
fq={!tag="tag1"}state:California
,定一个了一个队state字段的过滤器,并命名为tag1,然后在facet的field定义时使用tag标签facet.field={!ex=tag1}state
,这样state分面就会忽略标记为tag1的过滤器,也就是这个过滤器对state字段不进行过滤。