Hibernate 搜索:使用 Ngram 过滤器对数据进行索引,并且在搜索时由于查询时标记化而给出不正确的结果

问题描述 投票:0回答:1

我有一个具有此配置的分析仪,

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

java hibernate elasticsearch lucene hibernate-search
1个回答
2
投票

上面的 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
    。您将获得代币列表。
  • 创建 Lucene
    Query
    :本质上它将是一个布尔查询,每个标记都有一个
    TermQuery
  • 照常将结果
    Query
    传递给 Hibernate Search。

或者在 hibernate-search 6.x 版本中是否以更简单的方式以其他方式处理?

Hibernate Search 6 及更高版本中,这非常简单。解决办法有两种:

但请注意,Hibernate Search 6 尚不支持动态字段:HSEARCH-3273

© www.soinside.com 2019 - 2024. All rights reserved.