Java Hibernate搜索:使用Ngram筛选器索引数据,搜索时由于查询时标记化而给出不正确的结果
我有一个这样配置的分析器Java Hibernate搜索:使用Ngram筛选器索引数据,搜索时由于查询时标记化而给出不正确的结果,java,hibernate,
elasticsearch,lucene,hibernate-search,Java,Hibernate,
elasticsearch,Lucene,Hibernate Search,我有一个这样配置的分析器 searchMapping// .analyzerDef(BaseEntity.CUSTOM_SEARCH_INDEX_ANALYZER, WhitespaceTokenizerFactory.class)// .filter(LowerCaseFilterFactory.class)// .filter(ASCIIFoldingFilterFactory.class)// .filter(NGramFil
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搜索生成的查询
正在执行Lucene查询'++++
书名:x
书名:xg
书名:g
上面的Lucene查询是使用BooleanJunction::must conditions by Lucene准备的,我猜这意味着它应该匹配所有条件。
还是为什么它给我两个实体数据。我不明白这里
我也可以在查询时通过使用关键字标记器而不是NGramFilterFactory来覆盖分析器,但这就像我必须在创建QueryBuilder之前覆盖每个字段一样,这看起来不太好,因为我必须覆盖所有索引字段,我有大约100个字段,其中一些是动态字段,我创建了每个字段的单独查询
在5.11版本中是否有其他方法覆盖分析器,或者在HibernateSearch6.x版本中是否有其他更简单的方法处理分析器
我使用的Hibernate版本是
hibernate搜索elasticsearch,hibernate搜索orm=5.11.4.Final
上面的Lucene查询是使用BooleanJunction::must conditions by Lucene准备的,我猜这意味着它应该匹配所有条件。还是为什么它给我两个实体数据。我不明白这里
使用Hibernate Search创建关键字查询时,将分析传递给该查询的字符串,如果有多个标记,Hibernate Search将创建一个布尔查询,每个标记对应一个should子句。您可以在这里看到它bookName:x bookName:xg bookName:g:bookName前面没有+符号,这意味着这些不是must子句,而是should子句
我也可以在查询时通过使用关键字标记器而不是NGramFilterFactory来覆盖分析器,但这就像我必须在创建QueryBuilder之前覆盖每个字段一样,这看起来不太好,因为我必须覆盖所有索引字段,我有大约100个字段,其中一些是动态字段,我创建了每个字段的单独查询
没错,那很烦人
在5.11版本中,是否有其他方法覆盖分析仪
在5.11中,我认为没有任何其他方法可以覆盖分析器
如果有必要,并且您使用的是Lucene后端,我相信您应该能够绕过Hibernate搜索DSL,只用于此特定查询:
获取所需的分析器:类似analyzer analyzer=fullTextSession.getSearchFactory.GetAnalyzerMyAnalyzer WithoutngRamTokenFilter。
分析搜索词:CallAnalyzer.tokenStream。。。并根据需要使用令牌流。您将得到一个令牌列表。
创建Lucene查询:本质上,它是一个布尔查询,每个令牌有一个TermQuery。
像往常一样将结果查询传递给Hibernate Search。
或者在HibernateSearch6.x版本中,它是以其他更简单的方式处理的
在HibernateSearch 6.0.0.Beta4中非常简单。有两种解决方案:
隐式:在映射中,不仅可以指定using@FullTextFieldanalyzer=myAnalyzer,还可以指定using@FullTextFieldanalyzer=myAnalyzer、searchAnalyzer=mySearchAnalyzer。索引时将使用默认分析器,而搜索查询时将使用搜索分析器。
显式:在查询时,您可以通过在构建谓词时调用.analyzermySearchAnalyzer来覆盖给定谓词上的分析器。有一个例子。
但是请注意,Hibernate Search 6:中还不支持动态字段。谢谢您的宝贵意见。HibernateSearch6使用这些功能看起来很棒。作为一种解决方法,我只使用ASCII过滤器和小写过滤器配置了规范化器,对于部分匹配,我使用通配符查询。我当然更喜欢解决方案1。期待HibernateSearch6.x版本的发布。