首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Hibernate搜索:用Ngram筛选器索引数据,在搜索时,由于查询时的标记,结果不正确。

Hibernate搜索:用Ngram筛选器索引数据,在搜索时,由于查询时的标记,结果不正确。
EN

Stack Overflow用户
提问于 2020-02-14 14:57:03
回答 1查看 452关注 0票数 0

我有一个带有这种配置的分析器

代码语言:javascript
复制
searchMapping//
        .analyzerDef(BaseEntity.CUSTOM_SEARCH_INDEX_ANALYZER, WhitespaceTokenizerFactory.class)//
        .filter(LowerCaseFilterFactory.class)//
        .filter(ASCIIFoldingFilterFactory.class)//
        .filter(NGramFilterFactory.class).param("minGramSize", "1").param("maxGramSize", "200");

这是如何配置我的实体字段的。

代码语言:javascript
复制
@Field(analyzer = @Analyzer(definition = CUSTOM_SEARCH_INDEX_ANALYZER))
private String bookName;

这就是我如何创建搜索查询的方式。

代码语言:javascript
复制
queryBuilder.keyword().onField(prefixedPath).matching(matchingString).createQuery()

我有一个bookName=值为“格列佛”的实体和另一个具有bookName=“xGulliver”的实体;

如果我试图使用数据bookName = xG进行搜索,那么就会得到两个实体,我希望实体只能使用bookName="xGulliver";还可以查看hibernate-search生成的查询。

执行Lucene query‘+( bookName:xg :xg:G)

上面的Lucene查询是由Lucene使用BooleanJunction::must条件编写的,这意味着它应该匹配所有的条件。为什么它给了我两个实体数据。我不明白这里。

我还可以在查询时重写分析器,方法是使用KeywordTokenizer而不是NGramFilterFactory,但这就好像在创建QueryBuilder之前必须重写每个字段,这看起来不太好,因为我必须覆盖所有索引字段,其中包括大约100个字段,有些是动态字段,然后为每个字段创建单独的查询。

有没有其他方法在5.11版本中覆盖分析器,或者在hibernate-Search6.x版本中是否以更简单的方式处理?

我使用的Hibernate版本是,

hibernate-搜索-elasticsearch,hibernate-搜索-orm=5.11.4

EN

回答 1

Stack Overflow用户

发布于 2020-02-17 07:53:30

上面的Lucene查询是使用布尔conditions::must条件由Lucene准备的,我猜这意味着它应该匹配所有条件。为什么它给了我两个实体数据。我不明白这里。

使用Hibernate搜索创建keyword查询时,将分析传递给该查询的字符串,如果存在多个令牌,Hibernate搜索将为每个令牌创建一个带有一个“应当”子句的布尔查询。您可以在这里看到“bookName:::g”:在"bookName“之前没有"+”符号,这意味着这些不是“必须”子句,它们是“应该”子句。

我还可以在查询时重写分析器,方法是使用KeywordTokenizer而不是NGramFilterFactory,但这就好像在创建QueryBuilder之前必须重写每个字段,这看起来不太好,因为我必须覆盖所有索引字段,其中包括大约100个字段,有些是动态字段,然后为每个字段创建单独的查询。

是啊,真烦人。

有没有其他方法覆盖5.11版本的分析器?

在5.11,我不认为有任何其他方式来覆盖分析器。

如果有必要的话,如果您正在使用Lucene后端,我相信您应该能够绕过Hibernate搜索DSL,只用于这个特定的查询:

  • 获取您想要的分析器:类似于Analyzer analyzer = fullTextSession.getSearchFactory().getAnalyzer("myAnalyzerWithoutNGramTokenFilter")
  • 分析搜索条件:调用analyzer.tokenStream(...)并酌情使用TokenStream。你会得到一张代币的清单。
  • 创建Lucene Query:本质上它将是一个布尔查询,每个令牌都有一个TermQuery
  • 像往常一样,将结果的Query传递给Hibernate搜索。

还是在hibernate-Search6.x版本中以更简单的方式处理呢?

在Hibernate搜索6.0.0.Beta 4中,它非常简单。有两种解决办法:

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

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60228692

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档