lucene 休眠搜索:使用Ngram筛选器对数据进行索引,搜索时由于查询时的标记化而给出错误结果

wvt8vs2t  于 2022-11-07  发布在  Lucene
关注(0)|答案(1)|浏览(141)

我有一台分析仪,

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版本包括,
在这个例子中,我们使用了一个简单的方法,即:

djmepvbi

djmepvbi1#

上面的Lucene查询是用Lucene的BooleanJunction::must条件准备的,我想这意味着它应该匹配所有的条件。但是为什么它给我两个实体数据。我不明白这里。
使用Hibernate搜索创建keyword查询时,将分析传递给该查询的字符串,如果有多个标记,Hibernate搜索将为每个标记创建一个带有一个“should”子句的布尔查询。您可以在此处看到“bookName:x bookName:xg bookName:g”:在“bookName”前面没有“+”号,这意味着那些不是“must”子句,它们是“should”子句。
我还可以在查询时使用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搜索。

或者在hibernate-search 6.x版本中以其他方式更简单地处理它?
在Hibernate Search 6.0.0.Beta4中,这非常简单。有两种解决方案:

  • 隐式:在Map中,您不仅可以指定分析器(使用@FullTextField(analyzer = "myAnalyzer")),还可以使用@FullTextField(analyzer = "myAnalyzer", searchAnalyzer = "mySearchAnalyzer")指定“搜索”分析器。“默认”分析器将在索引时使用,而“搜索”分析器将在搜索(查询)时使用。
  • 显式:在查询时,可以通过在构建 predicate 时调用.analyzer("mySearchAnalyzer")来覆盖给定 predicate 上的分析器。文档的这一节中有一个示例。

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

相关问题