Lucene Hibernate Search | ngram分析器,具有minGramSize 1
我的Hibernate搜索分析器配置有一些问题。 我的一个索引实体(“医院”)有一个字符串字段(“名称”),可以包含长度为1-40的值。我希望能够通过搜索一个字符来找到实体(因为医院可能只有一个字符名) 如果添加名为“我的测试医院”的医院,Lucene索引如下所示:Lucene Hibernate Search | ngram分析器,具有minGramSize 1,lucene,hibernate-search,n-gram,analyzer,Lucene,Hibernate Search,N Gram,Analyzer,我的Hibernate搜索分析器配置有一些问题。 我的一个索引实体(“医院”)有一个字符串字段(“名称”),可以包含长度为1-40的值。我希望能够通过搜索一个字符来找到实体(因为医院可能只有一个字符名) 如果添加名为“我的测试医院”的医院,Lucene索引如下所示: 1 name al 1 name e 1 name es 1 name est 1 name h 1 name ho 1 name hos 1 name
1 name al
1 name e
1 name es
1 name est
1 name h
1 name ho
1 name hos
1 name hosp
1 name hospi
1 name hospit
1 name hospita
1 name hospital
1 name i
1 name it
1 name ita
1 name ital
1 name l
1 name m
1 name my
1 name o
1 name os
1 name osp
1 name ospi
1 name ospit
1 name ospita
1 name ospital
1 name p
1 name pi
1 name pit
1 name pita
1 name pital
1 name s
1 name sp
1 name spi
1 name spit
1 name spita
1 name spital
1 name st
1 name t
1 name ta
1 name tal
1 name te
1 name tes
1 name test
1 name y
1 name a
以下是我构建和执行搜索查询的方式:
QueryBuilder hospitalQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Hospital.class).get();
Query hospitalQuery = hospitalQb.keyword().onFields("name")().matching(searchString).createQuery();
javax.persistence.Query persistenceQuery = fullTextEntityManager.createFullTextQuery(hospitalQuery, Hospital.class);
List<Hospital> results = persistenceQuery.getResultList();
所以问题是,有人知道更好的analyzer配置或其他构建搜索查询的方法来解决问题吗 您可以设置第二台分析仪,除了没有ngram过滤器外,其他功能相同,然后覆盖用于查询的分析仪:
QueryBuilder hospitalQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Hospital.class)
.overridesForField( "name", "my_analyzer_without_ngrams" )
.get();
// Then it's business as usual
此外,如果您正在实现某种自动完成(
foo*
),而不是在word搜索(*foo*
)中,您可能希望使用EdgeNGramFilterFactory
而不是NGramFilterFactory
:它将只生成作为索引令牌前缀的Ngram。您可以设置第二个分析器,相同,只是它没有ngram过滤器,然后覆盖用于查询的分析器:
QueryBuilder hospitalQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Hospital.class)
.overridesForField( "name", "my_analyzer_without_ngrams" )
.get();
// Then it's business as usual
此外,如果您正在实现某种自动补全(
foo*
),而不是在单词搜索(*foo*
)中,您可能希望使用EdgeNGramFilterFactory
而不是NGramFilterFactory
:它只会生成作为索引标记前缀的ngram。Yoann的回答是正确的,添加了一些建议:不要使用如此大的maxGramSize
:对于大多数用例,选择3或4。此外,您可能希望使用多个@field注释为同一字段编制索引:为每个字段指定不同的名称和不同的分析器,然后在查询时执行针对这两个字段的布尔查询,每个都有正确的分析器。Yoann的回答是正确的,并添加了一些建议:不要使用如此大的maxGramSize
:对于大多数用例,选择3或4。此外,您可能希望使用多个@field注释为同一字段编制索引:为每个字段指定不同的名称和不同的分析器,然后在查询该字段时,使用正确的分析器针对这两个字段执行布尔查询。谢谢您的帮助。这几乎解决了问题,但是否有可能覆盖所有字段的分析器?我有许多具有相同问题的嵌入式索引实体。所以我必须重写它们所有(.overridesForField(“careUnits.name”…)也许可以加载一个“my_analyzer”的实例,而不使用“ngrams”通过编程并使用此实例生成搜索查询?@Andre您能提供您正在使用的实际代码吗?我在原始问题中只看到一个字段,因此我看不出问题的确切原因,解决方案可能会根据问题的性质而有所不同。您是否生成一个针对多个字段的查询?多个查询,each针对单个字段?其他?在最初的问题中,我试图分解复杂性。我在实际实现中有更多的索引实体。这就是我目前实现搜索的方式:。它是这样工作的,但在我看来,所有字段的手动覆盖都有点脏。因此,如果你知道一个更好的方法为了解决这个问题,我会很高兴你的解决方案。谢谢你的帮助和你的时间。好的,从你正在做的事情来看,你最好使用org.apache.lucene.queryparser.simple.simplequalyparser
解析搜索字符串。只需使用simplequalyparser(Analyzer Analyzer,Map weights)
constructor,并通过执行fullTextSession.getSearchFactory().getAnalyzer(“搜索”)检索您的分析器
。请注意,我们正在进行中,但在5.8之前,最多几周内将无法提供。@yrodiere我对这个答案很感兴趣,但您能否更详细地解释覆盖的工作原理?也许可以举个例子?谢谢您的帮助。这几乎解决了问题,但是否有可能覆盖所有f的分析器IELD?我有许多具有相同问题的嵌入式索引实体。因此我必须覆盖它们所有(.overridesForField(“careUnits.name”…)也许可以加载“my_analyzer”的实例,而不加载任何内存通过编程并使用此实例生成搜索查询?@Andre您能提供您正在使用的实际代码吗?我在原始问题中只看到一个字段,因此我看不出问题的确切原因,解决方案可能会根据问题的性质而有所不同。您是否生成一个针对多个字段的查询?多个查询,each针对单个字段?其他?在最初的问题中,我试图分解复杂性。我在实际实现中有更多的索引实体。这就是我目前实现搜索的方式:。它是这样工作的,但在我看来,所有字段的手动覆盖都有点脏。因此,如果你知道一个更好的方法为了解决这个问题,我会很高兴你的解决方案。谢谢你的帮助和你的时间。好的,从你正在做的事情来看,你最好使用org.apache.lucene.queryparser.simple.simplequalyparser
解析搜索字符串。只需使用simplequalyparser(Analyzer Analyzer,Map weights)
constructor,并通过执行fullTextSession.getSearchFactory().getAnalyzer(“搜索”)检索您的分析器
。请注意,我们正在进行中,但在5.8之前,最多几周内无法提供该选项。@yrodiere我对这个答案很感兴趣,但您能否更详细地解释覆盖的工作原理?也许可以举个例子?
QueryBuilder hospitalQb = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(Hospital.class)
.overridesForField( "name", "my_analyzer_without_ngrams" )
.get();
// Then it's business as usual