我有一个具有此配置的分析仪,
searchMapping//
.analyzerDef(BaseEntity.CUSTOM_SEARCH_INDEX_ANALYZER, WhitespaceTokenizerFactory.class)//
.filter(LowerCaseFilterFactory.class)//
.filter(ASCIIFoldingFilterFactory.class)//
.filter(NGramFilterFactory.class).param("minGramSize", "1").param("maxGramSize", "200");
这就是我的实体字段的配置方式
@Field(analyzer = @Analyzer(definition = CUSTOM_SEARCH_INDEX_ANALYZER))
private String bookName;
这就是我创建搜索查询的方式
queryBuilder.keyword().onField(prefixedPath).matching(matchingString).createQuery()
我有一个值为 bookName="Gulliver" 的实体和另一个值为 bookName="xGulliver" 的实体;
如果我尝试使用数据进行搜索
bookName = xG
,那么我会得到两个实体,而我只希望实体具有bookName="xGulliver"
;
还查看了 hibernate-search 生成的查询。
执行 Lucene 查询 '+(+(+(+( 书名:x 书名:xg 书名:g))))
上面的 Lucene 查询是使用 Lucene 的
BooleanJunction::must
条件准备的,我想这意味着它应该匹配所有条件。
仍然为什么它给我两个实体数据。这里我不太明白。
我还可以在查询时通过使用 KeywordTokenizer 而不是 NGramFilterFactory 来覆盖分析器,但这就像我必须在创建 QueryBuilder 之前覆盖每个字段,这看起来不太好,因为然后我必须覆盖我有大约 100 个字段的所有索引字段有些是动态字段,我为每个字段创建单独的查询。
是否有其他方法可以覆盖 5.11 版本中的分析器,或者是否在 hibernate-search 6.x 版本中以更简单的方式以其他方式处理分析器?
我使用的 Hibernate 版本是,
hibernate-search-elasticsearch,hibernate-search-orm = 5.11.4.Final
上面的 Lucene 查询是使用 Lucene 的 BooleanJunction::must 条件准备的,我想这意味着它应该匹配所有条件。仍然为什么它给我两个实体数据。这里我不太明白。
当您使用 Hibernate Search 创建
keyword
查询时,系统会分析传递给该查询的字符串,如果有多个标记,Hibernate Search 会创建一个布尔查询,其中每个标记都有一个“should”子句。你可以在这里看到“bookName:x bookName:xg bookName:g”:“bookName”之前没有“+”号,这意味着这些不是“必须”子句,而是“应该”子句。
我还可以在查询时通过使用 KeywordTokenizer 而不是 NGramFilterFactory 来覆盖分析器,但这就像我必须在创建 QueryBuilder 之前覆盖每个字段,这看起来不太好,因为然后我必须覆盖我有大约 100 个字段的所有索引字段有些是动态字段,我为每个字段创建单独的查询。
确实,这很烦人。
有没有其他方法可以覆盖5.11版本中的分析器
在5.11中,我认为没有其他方法可以覆盖分析器。
如果有必要并且您正在使用 Lucene 后端,我相信您应该能够针对此特定查询绕过 Hibernate Search DSL:
Analyzer analyzer = fullTextSession.getSearchFactory().getAnalyzer("myAnalyzerWithoutNGramTokenFilter")
。analyzer.tokenStream(...)
并根据需要使用 TokenStream
。您将获得代币列表。Query
:本质上它将是一个布尔查询,每个标记都有一个 TermQuery
。Query
传递给 Hibernate Search。或者在 hibernate-search 6.x 版本中是否以更简单的方式以其他方式处理?
在 Hibernate Search 6 及更高版本中,这非常简单。解决办法有两种:
@FullTextField(analyzer = "myAnalyzer")
),还可以使用@FullTextField(analyzer = "myAnalyzer", searchAnalyzer = "mySearchAnalyzer")
指定“搜索”分析器。索引时将使用“默认”分析器,而搜索(查询)时将使用“搜索”分析器。
.analyzer("mySearchAnalyzer")
来覆盖给定谓词上的分析器。 文档的这一节中有一个示例。但请注意,Hibernate Search 6 尚不支持动态字段:HSEARCH-3273。