elasticsearch,lucene,hibernate-search,Java,Hibernate,elasticsearch,Lucene,Hibernate Search" /> elasticsearch,lucene,hibernate-search,Java,Hibernate,elasticsearch,Lucene,Hibernate Search" />

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版本的发布。