7.5.3. Faceting
分面搜索是一种将查询结果划分为多个类别的技术。这种分类包括每个类别的点击数计算,以及根据这些方面进一步限制搜索结果的能力(说明)。以下示例显示了一个现实示例。搜索结果以 15 次命中显示在页面主部分中。但是,左侧的导航栏显示了计算机和互联网类别及其子类别 编程、计算机科学、数据库、软件、Web 开发、 网络和家庭 计算。对于每个子类别,显示图书数量与主要搜索标准相符,并属于相应的子类别。这种"计算机和互联网"类别划分是一个具体的搜索面。另一个是平均客户评论。
分面搜索将查询的结果划分为不同的类别。分类包括每个类别的点击数计算,并根据这些方面(类别)进一步限制搜索结果。以下示例在主页面中以 15 个命中显示单面搜索结果。
左侧导航栏显示类别和子类别。对于每个子类别,图书的数量都与主要搜索标准匹配,并属于相应的子类别。这种"计算机和互联网"类别划分是一个具体的搜索面。另一个例子是平均客户评论。
示例:在 Amazon 上搜索 Hibernate Search
在 Hibernate Search 中,类 QueryBuilder 和 FullTextQuery 是面临 API 的入口点。前者会创建各种请求,后者将访问 FacetManager。FacetManager 对查询应用各种请求,并选择添加到现有查询中的侧面,以优化搜索结果。示例使用实体 Cd,如下例所示:
示例:实体 Cd
@Indexed
public class Cd {
private int id;
@Fields( {
@Field,
@Field(name = "name_un_analyzed", analyze = Analyze.NO)
})
private String name;
@Field(analyze = Analyze.NO)
@NumericField
private int price;
Field(analyze = Analyze.NO)
@DateBridge(resolution = Resolution.YEAR)
private Date releaseYear;
@Field(analyze = Analyze.NO)
private String label;
// setter/getter
...
在 Hibernate Search 5.2 之前,无需显式使用 @Facet 注释。在 Hibernate Search 5.2 中,为了使用 Lucene 的原生面 API,有必要使用 Lucene。
7.5.3.1. 创建 Faceting 请求 复制链接链接已复制到粘贴板!
进行分面搜索的第一步是创建 FacetingRequest。目前支持两种类型的相互竞争请求。第一种类型称为离散面,第二个类型 范围则面临请求。如果是离散的面貌请求,您可以指定您要在哪个索引字段上查看(分类)以及要应用哪些选项。以下示例中显示了离散侧面请求的示例:
示例:创建离散 Faceting 请求
QueryBuilder builder = fullTextSession.getSearchFactory()
.buildQueryBuilder()
.forEntity( Cd.class )
.get();
FacetingRequest labelFacetingRequest = builder.facet()
.name( "labelFaceting" )
.onField( "label")
.discrete()
.orderedBy( FacetSortOrder.COUNT_DESC )
.includeZeroCounts( false )
.maxFacetCount( 1 )
.createFacetingRequest();
在执行此竞争请求时,将为索引化字段 标签 的每个离散值创建 Facet 实例。Facet 实例将记录实际字段值,包括此特定字段值在原始查询结果中发生的频率。orderBy、includeZeroCounts 和 maxFacetCount 是可选参数,可在任何面临请求时应用。OrderBy 允许指定返回所创建面的顺序。默认值为 FacetSortOrder.COUNT_DESC,但您也可以根据字段值或指定范围的顺序排序。includeZeroCount 决定结果中是否包括数为 0 的面数(默认为 ),而 maxFacetCount 允许限制返回的最大面数。
目前,索引化字段必须满足几个前提条件才能对其应用。索引化属性必须是 String、Date 或 Number 和 null 值的子类型。此外,该属性必须使用 Analyze .NO 进行索引,如果是数值属性 @NumericField,则需要指定。
范围侧面请求的创建非常相似,除非我们必须为所面对的字段值指定范围。下面列出了指定了三个不同价格范围的范围。以下 及以上 只能指定一次,但您可以根据需要 从 - 指定为 范围。对于每个范围边界,您还可以通过 excludeLimit 来指定它是否包含在范围中。
示例:创建一个范围 Faceting 请求
QueryBuilder builder = fullTextSession.getSearchFactory()
.buildQueryBuilder()
.forEntity( Cd.class )
.get();
FacetingRequest priceFacetingRequest = builder.facet()
.name( "priceFaceting" )
.onField( "price" )
.range()
.below( 1000 )
.from( 1001 ).to( 1500 )
.above( 1500 ).excludeLimit()
.createFacetingRequest();