Hibernate Search:在同一字段上可搜索和可排序

Hibernate Search: searchable and sortable on the same field

我正在使用 hibernate search 5.11.1 并且需要在相同的字符串类型字段上支持可搜索和可排序。阅读 reference guide 后,我找到了以下有关使用规范化器对分析文本进行排序的文档。

参考官方指南:

Analyzers are great when you need to search in text documents, but what if you want to sort the analyzed text? Then you’re in for a bit of trouble, because analyzed text is multi-valued: when indexing a book with the title "Refactoring: Improving the Design of Existing Code", the analyzed title is in fact the (unordered) set {"refactoring", "improving", "design", "existing", "code"}. If you tried to sort on the title after such an analysis, any of those words could be used, so your book could end up in the D’s (because of "design"), or in the R’s (because of "refactoring"), or in the E’s, etc.

So in the end, you probably don’t want your fields to be tokenized when you sort on those fields. Normalizers solve exactly this issue: they are analyzers, but without a tokenizer, and with some runtime checks that prevent the analysis to produce multiple tokens, thereby ensuring your sorts will always be consistent.

Hibernate Search provides normalizer equivalent for relevant analyzer annotations: @Normalizer, @NormalizerDef, @NormalizerDefs. As with analyzer, you can use implementations directly (for instance @Normalizer(impl = MyCollactionKeyAnalyzer.class)) or named normalizers (for instance @Normalizer(definition = "myNormalizer") with @NormalizerDef(filters = @TokenFilterDef(factory = LowerCaseFilterFactory.class)).

基于以上,我写了如下代码:

@Entity
@Indexed
@AnalyzerDef(name = "en", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class),
        filters = {
                @TokenFilterDef(factory = LowerCaseFilterFactory.class),
                @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class)
        })
@NormalizerDef(name = "lowercase", filters = {
                @TokenFilterDef(factory = ASCIIFoldingFilterFactory.class),
                @TokenFilterDef(factory = LowerCaseFilterFactory.class)
        }
)
@Table(name = "ORDER")
public class Order {

    //Some other fields that are omitted for brevity here

    @Field(name = "orderName_Search", store = Store.YES, analyze = Analyze.YES, analyzer = @Analyzer(definition = "en"))
    @Field(name = "orderName_Sort", store = Store.YES, analyze = Analyze.NO, normalizer = @Normalizer(definition = "lowercase"))
    @SortableField(forField = "orderName_Sort")
    @Column(name = "ORDER_NAME")
    private String orderName;

}

但是,它似乎不起作用,因为我 运行 出现以下错误。

[错误] com.appnexus.konnect.web.exceptions.ConnectExceptionHandler - 异常 org.hibernate.search.exception.SearchException: 无法自动确定字段 'orderName' 的字段类型。使用 byField(String, Sort.Type) 明确提供排序类型

我的问题是哪里出错了?它仅在使用 @Field 注释时有效,但在同时使用时失败。

从报错信息来看,你好像是这样写的:

qb.sort().byField("orderName").createSort()

但是就 Hibernate Search 而言,orderName 字段不存在。只有 orderName_SearchorderName_Sort 存在。在这种情况下你应该写:

qb.sort().byField("orderName_Sort").createSort()

此外,请注意,在 orderName_Sort 上设置 analyze = Analyze.NO 将有效地禁用您的规范器。您可能想忽略它。