lucene - 使用休眠搜索以单词开头或以单词结尾
问题描述
我正在使用带有 spring-boot 的 Hibernate Search。我要求用户必须让搜索运算符对机构名称执行以下操作:
- 以一句话开头
.Ali --> 表示该短语应严格以 Ali 开头,这意味着 AlAli 不应在结果中返回
query = queryBuilder.keyword().wildcard().onField("establishmentNameEn")
.matching(term + "*").createQuery();
它返回的混合结果包含中间、开始或结尾的术语,不符合上述要求
- 以一句话结尾
卡姆兰。--> 表示应该严格结束Kamran,意思是结果中不应该返回Kamranullah
query = queryBuilder.keyword().wildcard().onField("establishmentNameEn")
.matching("*"+term).createQuery();
根据文档,将“*”放在开头并不是一个好主意。我的问题是:我怎样才能达到预期的结果
我的域类和分析器:
@AnalyzerDef(name = "english", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class), })
@Indexed
@Entity
@Table(name = "DIRECTORY")
public class DirectoryEntity {
@Analyzer(definition = "english")
@Field(store = Store.YES)
@Column(name = "ESTABLISHMENT_NAME_EN")
private String establishmentNameEn;
getter and setter
}
解决方案
这里有两个问题:
标记化
您正在使用分词器,这意味着您的搜索将使用单词,而不是您索引的完整字符串。这说明您在句子中间的术语上得到匹配。
这可以通过为这些特殊的开始/结束查询创建一个单独的字段来解决,并使用带有 的分析器KeywordTokenizer
(这是一个无操作)。
例如:
@AnalyzerDef(name = "english", tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class), filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class), })
@AnalyzerDef(name = "english_beginEnd", tokenizer = @TokenizerDef(factory = KeywordTokenizerFactory.class), filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class), })
@Indexed
@Entity
@Table(name = "DIRECTORY")
public class DirectoryEntity {
@Analyzer(definition = "english")
@Field(store = Store.YES)
@Field(name = "establishmentNameEn_beginEnd", store = Store.YES, analyzer = @Analyzer(definition = "english_beginEnd"))
@Column(name = "ESTABLISHMENT_NAME_EN")
private String establishmentNameEn;
getter and setter
}
查询分析和性能
通配符查询不会触发对输入文本的分析。这将导致意外行为。例如,如果您索引“Ali”,然后搜索“ali”,您可能会得到结果,但如果您搜索“Ali”,则不会:文本被分析并索引为“ali”,这不会t 完全匹配“阿里”。
此外,如您所知,前导通配符在性能方面非常非常糟糕。
如果您的字段长度合理(例如,少于 30 个字符),我建议改用“edge-ngram”分析器;你会在这里找到解释:Hibernate Search:如何正确使用通配符?
请注意,您仍然需要使用KeywordTokenizer
(与我链接的示例不同)。
这将处理“匹配文本的开头”查询,而不是“匹配文本的结尾”查询。
为了解决第二个查询,我将创建一个单独的字段和一个单独的分析器,类似于用于第一个查询的分析器,唯一的区别是您ReverseStringFilterFactory
在EdgeNGramFilterFactory
. 这将在索引 ngram 之前反转文本,这将导致所需的行为。不要忘记对该字段使用单独的查询分析器,它可以反转字符串。
推荐阅读
- r - 从 H2O AutoML 排行榜中提取模型
- excel - 关闭 Microsoft Azure 信息保护栏
- bash - echo 未输入到哈希表中
- node.js - 一个特定的“socket.on()”在客户端不起作用
- c++ - 为什么我不能使用 msvc 在模板类中声明静态 constexpr 变量?
- vb.net - VB.Net | 有没有办法引用动态数量的变量作为函数/子的参数?
- php - wp core install 无法使用 WP-CLI 连接到数据库
- sql - 如何运行顺序临时表和最终 SELECT 查询
- r - 排名并选择每组显示最佳结果的 5 个模型
- mysql - 如何在 ionic 4 客户端应用程序和快速服务器之间建立连接?