- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试创建 StingUtils 的 Hibernate 搜索表示 containsIgnoreCase()方法与模糊搜索匹配相结合。
假设用户写入字母“p”,他们将获得包含字母“p”的所有匹配项(无论该字母位于各个匹配项的开头、中间还是末尾)。
当它们形成“Peter”等单词时,它们也应该收到模糊匹配,例如“Petar”、“Petaer”和“Peder”。
我正在使用出色的答案 here 中提供的自定义查询和索引分析器,因为我需要 minGramSize
为 1 以允许自动完成功能,同时我还期望用空格分隔的多词用户输入,例如“EUR Account of Peter”,这可以是在不同的情况下(较低或较高)。
因此,用户应该能够键入“AND”并接收上述示例作为匹配项。
目前,我正在使用以下查询:
org.apache.lucene.search.Query fuzzySearchByName = qb.keyword().fuzzy()
.withEditDistanceUpTo(1).onField("name")
.matching(userInput).createQuery();
booleanQuery.add(fuzzySearchByName, BooleanClause.Occur.MUST);
但是,完全匹配案例不会出现在搜索结果中:
如果我们输入“petar”,我们会得到以下结果:
... 4.PETAR(完全匹配)
同样适用于用户输入“peter”,其中第一个结果是“Petero”,第二个结果是“Peter”(第二个结果应该是第一个结果)。
我还需要仅包含多词查询的精确匹配 - 例如如果我开始写“Account for...”,我希望所有匹配结果都包含短语“Account for”,并最终包含基于该短语的模糊相关术语短语(与前面展示的 containsIgnoreCase() 方法基本相同,只是尝试添加模糊支持)。
但是我猜这与 minGramSize
为 1 和 WhitespaceTokenizerFactory
是矛盾的?
最佳答案
However, exact match cases do not receive presendence in the search results:
只需使用两个查询而不是一个:
编辑:您还需要为自动完成和“精确”匹配设置两个单独的字段;请参阅底部的我的编辑。
org.apache.lucene.search.Query exactSearchByName = qb.keyword().onField("name")
.matching(userInput).createQuery();
org.apache.lucene.search.Query fuzzySearchByName = qb.keyword().fuzzy()
.withEditDistanceUpTo(1).onField("name")
.matching(userInput).createQuery();
org.apache.lucene.search.Query searchByName = qb.boolean().should(exactSearchByName).should(fuzzySearchByName).createQuery();
booleanQuery.add(searchByName, BooleanClause.Occur.MUST);
这将匹配包含完全或用户输入的文档,因此这将匹配与您的示例相同的文档。但是,完全包含用户输入的文档将匹配两个查询,而仅包含相似内容的文档将仅匹配模糊查询。因此,完全匹配的分数会更高,并且在结果列表中的排名也会更高。
如果精确匹配不够高,请尝试向 exactSearchByName
查询添加提升:
org.apache.lucene.search.Query exactSearchByName = qb.keyword().onField("name")
.matching(userInput)
.boostedTo(4.0f)
.createQuery();
I guess however that this contradics with the minGramSize of 1 and the WhitespaceTokenizerFactory?
如果您想要匹配包含用户输入中出现的任何单词(但不一定是所有单词)的文档,并将包含更多单词的文档放在结果列表中更高的位置,请按照我上面的说明进行操作。
如果您想要匹配包含完全相同顺序的所有单词的文档,请使用 KeywordTokenizerFactory
(即不进行标记)。
如果您想匹配包含任意顺序的所有单词的文档,那么...这不太明显。 Hibernate Search ( yet ) 不支持这一点,因此您基本上必须自己构建查询。我已经见过的一种黑客行为是这样的:
Analyzer analyzer = fullTextSession.getSearchFactory().getAnalyzer( "myAnalyzer" );
QueryParser queryParser = new QueryParser( "name", analyzer );
queryParser.setOperator( Operator.AND ); // Match *all* terms
Query luceneQuery = queryParser.parse( userInput );
...但这不会生成模糊查询。如果你想要模糊查询,你可以尝试重写 QueryParser 的自定义子类中的一些方法。我没有尝试过这个,但它可能有效:
public final class FuzzyQueryParser extends QueryParser {
private final int maxEditDistance;
private final int prefixLength;
public FuzzyQueryBuilder(String fieldName, Analyzer analyzer, int maxEditDistance, int prefixLength) {
super( fieldName, analyzer );
this.maxEditDistance = maxEditDistance;
this.prefixLength = prefixLength;
}
@Override
protected Query newTermQuery(Term term) {
return new FuzzyQuery( term, maxEditDistance, prefixLength );
}
}
编辑:当 minGramSize 为 1 时,您将获得大量非常频繁的术语:从单词开头提取的单个或两个字符的术语。它可能会导致许多不需要的匹配,这些匹配将获得高分(因为术语很频繁),并且可能会淹没精确匹配。
首先,您可以尝试将相似度(~评分公式)设置为org.apache.lucene.search.similarities.BM25Similarity
,这样可以更好地忽略非常频繁的术语。请参阅here for the setting 。这应该会提高使用相同分析器的得分。
其次,您可以尝试设置两个字段而不是一个:一个字段用于模糊自动完成,另一个字段用于非模糊、完整匹配。这可能会提高精确匹配的分数,因为用于精确匹配的字段索引的无意义术语会减少。只需这样做:
@Field(name = "name", analyzer = @Analyzer(definition = "text")
@Field(name = "name_autocomplete", analyzer = @Analyzer(definition = "edgeNgram")
private String name;
分析器“text”只是 answer you linked 中的分析器“edgeNGram_query” ;只需重命名即可。
继续编写两个查询,而不是如上所述的一个,但请确保针对两个不同的字段:
org.apache.lucene.search.Query exactSearchByName = qb.keyword().onField("name")
.matching(userInput).createQuery();
org.apache.lucene.search.Query fuzzySearchByName = qb.keyword().fuzzy()
.withEditDistanceUpTo(1).onField("name_autocomplete")
.matching(userInput).createQuery();
org.apache.lucene.search.Query searchByName = qb.boolean().should(exactSearchByName).should(fuzzySearchByName).createQuery();
booleanQuery.add(searchByName, BooleanClause.Occur.MUST);
当然,不要忘记在这些更改之后重新索引。
关于java - 具有自动完成和模糊功能的 Hibernate 搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61251848/
什么是 hibernate 和n- hibernate ?我可以在 Visual Studio 2008 中使用它进行 C# Web 应用程序开发吗?请给我建议...我是 asp.net Web 应用
我有一个不系统地发生的异常(exception)。 我试图通过在每次迭代中刷新和清理 session 来解决此问题,但没有成功。 [quartzScheduler_Worker-7] ERROR jd
使用 Hibernate 在数据库中存储 IP 地址的最佳类型是什么? 我虽然是 Byte[] 或 String,但有没有更好的方法,或者你用什么? @Column(name = "range_fr
我正在尝试制定一个公式来选择用户个人资料的用户友好名称。它选择名字 + ' ' + 姓氏 如果其中至少有一个不为空且不为空(包含非空白字符),否则选择 短名称 (条件相同),最后,如果 短名称 为空或
在hibernate中,是否可以将鉴别器作为一个实体?例如,如果我将 Department 作为基类,将 AdminDepartment 和 ProcessingDepartment 作为子类。 De
我只想从表中获取一些列值。因此,我已经使用投影来实现这一目标。该代码有效,但我认为它无效。 我的问题是当我使用ProjectionsList并将标准条件列表设置为ArrayList时-Bulletin
你好: 我对 hibernate 缓存缓存的内容感到困惑。 从文档中,我知道 hibernate 中有缓存类型。 一级 :交易级别。 似乎要被 session 持久化的实体被缓存在这里。 二级缓存 :
我遇到了一个情况: save或update hibernate 的目标表中的某些数据 在目标表上有一个触发器,该触发器将在目标表的insert或update操作之前执行 由 hibernate 将此记
我有一个名为 Master_Info_tbl 的表。它是一个查询表: 这是该表的代码: @Entity @Table(name="MASTER_INFO_T") public class Code
我想知道如何在 Hibernate 查询语言中使用日期文字。我在我的 JPA 项目中做了如下操作(作为 Eclipselink 提供者)并且它工作正常。 SELECT m FROM Me m WHER
@Entity public class Troop { @OneToMany(mappedBy="troop") public Set getSoldiers() { ...
我正在尝试使用 hibernate 查询删除表 'user_role' 中的所有行。但每次我都会出错。有人可以帮我吗。 DaoImpl @Override public void deleteAll(
不是将数据库操作分散在四个 (osgi) 包中,而是在那里做略有不同的事情。我想创建一个负责所有持久性问题的(简单的)OSGi 包。我觉得这并不像听起来那么简单,因为“每个包都有独特的类加载器”。 因
这就是我使用生成器的方式: private Integer id; 我看到的行为是: 创建第一个对象 hibernate 分配 id = 1 删除该对象 关闭服务
对象级别的实体和值类型有什么区别。我知道实体将有一个 id 但值不会,但为什么我们需要不同的方法来映射实体与值类型? 这样做是为了让hibernate可以对值类型应用任何优化吗? 最佳答案 一个实体已
我正在使用 HibernateTemplate.findByCriteria 方法进行一些查询。现在我想在标准上创建一些 SQL 限制,比如 criteria.add(Restrictions.sql
所以我有以下代码: Query query = session.createQuery("from Weather"); List list = query.list();
如何使用Hibernate映射具有多个实体的 View ? 问候, 混沌 最佳答案 请参见Hibernate文档中第5.1.3节“类”,紧接在“Id”节之前: There is no differen
据我所知,Hibernate 有两种类型的实现 JPA的实现(2)(@Entity,@Table注解) 扩展到旧的(传统的) hibernate (没有 JPA),使用 HSQL 查询,没有注释 如果
我需要一个将条目存储为键值对的集合(因此我可以通过键查找值),但我需要一个允许多个值使用 hibernate 共享同一个键的集合 最佳答案 一个键具有多个值的映射称为多映射 - 在 Apache 公共
我是一名优秀的程序员,十分优秀!