gpt4 book ai didi

java - Hibernate搜索模糊超过2

转载 作者:行者123 更新时间:2023-12-01 17:27:56 24 4
gpt4 key购买 nike

我有一个带有 hibernate、lucene 和 hibernate-search 的 Java 后端。现在我想做一个模糊查询,但不是 0、1 或 2,我想允许查询和预期结果之间存在更多“差异”(以补偿长单词中的拼写错误)。有什么办法可以实现这一点吗?稍后将根据查询的长度计算允许的最大差异。
我想要这个的目的是自动完成搜索并纠正错误字母。此自动完成功能应仅搜索给定查询后面而不是前面的缺失字符。如果与条目相比,查询前面的字符丢失,则应将其计为差异。

示例:本示例中允许的最大不同字符数为 2。fooo 应该匹配

fooo       (no difference)
fooobar (only characters added -> autocomplete)
fouubar (characters added and misspelled -> autocomplete and spelling correction)

fooo 不应匹配

barfooo    (we only allow additional characters behind the query, but this example is less important)
fuuu (more than 2 differences)

这是我当前的 SQL 查询代码:

FullTextEntityManager fullTextEntityManager = this.sqlService.getFullTextEntityManager();
QueryBuilder queryBuilder = fullTextEntityManager.getSearchFactory().buildQueryBuilder().forEntity(MY_CLASS.class).overridesForField("name", "foo").get();
Query query = queryBuilder.keyword().fuzzy().withEditDistanceUpTo(2).onField("name").matching("QUERY_TO_MATCH").createQuery();
FullTextQuery fullTextQuery = fullTextEntityManager.createFullTextQuery(query, MY_CLASS.class);
List<MY_CLASS> results = fullTextQuery.getResultList();

注释:
1. 我使用 org.apache.lucene.analysis.ngram.EdgeNGramFilterFactory 进行索引,但这不应进行任何更改。
2.这是使用自定义框架,不是开源的。您可以忽略sqlService,它只提供FullTextEntityManager并处理hibernate周围的所有事情,不需要每次都自定义代码。
3. 此代码已经可以工作,但仅适用于 withEditDistanceUpTo(2),这意味着 QUERY_TO_MATCH 与数据库或索引中的匹配条目之间最多有 2 个“差异”。缺少的字符也算作差异。
4. withEditDistanceUpTo(2) 不接受大于 2 的值。

有人有任何想法来实现这一目标吗?

最佳答案

我不知道有任何解决方案可以指定允许的更改的确切数量。

无论如何,这种方法有严重的缺点:匹配“foo”最多 3 个更改意味着什么?只要匹配任何东西就可以吗?正如您所看到的,适用于不同期限长度的解决方案可能会更好。

一种解决方案是对 n 元词建立索引。我不是在谈论边缘 ngram,就像你已经做的那样,而是从整个术语中提取的实际 ngram,而不仅仅是边缘。因此,当索引 2 克的 foooo 时,您将索引:

  • fo
  • oo(出现多次)

查询时,术语fouuu将转换为:

  • fo
  • ou
  • uu

...它将匹配索引文档,因为它们至少有一个共同术语 (fo)。

显然有一些缺点。对于 2-gram,术语 fuuuu 不会匹配 foooo,但术语 barfooo 会匹配,因为它们有一个 2-gram 的共同点。所以你会得到误报。克数越长,出现误报的可能性就越小,但搜索的模糊性也就越低。

您可以通过依靠评分和按分数排序将最佳匹配项放在结果列表中的第一位来消除这些误报。例如,您可以配置 ngram 过滤器以保留原始术语,以便 fooo 将转换为 [fooo, fo, oo] 而不是 [fo, oo],因此精确搜索 fooo 将获得更好的分数包含 fooo 的文档比包含 barfooo 的文档(因为有更多匹配项)。您还可以设置多个单独的字段:一个没有 ngram,一个有 3-gram,一个有 2-gram,并为每个字段构建一个带有 on should 子句的 boolean 查询:匹配的子句越多,分数越高,您在点击中找到的文档就越高。

此外,我认为 fooo 和类似的实际上是人为的示例,并且您不太可能在现实世界的数据集中拥有这些术语;你应该尝试针对真实数据集提出的任何解决方案,看看它是否足够好。如果您想要模糊搜索,则必须接受一些误报:问题不在于它们是否存在,而在于它们是否足够稀有,以至于用户仍然可以轻松找到他们正在寻找的内容。

为了使用 ngram,请使用 org.apache.lucene.analysis.ngram.NGramFilterFactory 应用 n-gram 过滤器。在索引和查询时都应用它。使用参数 minGramSize/maxGramSize 配置 ngram 的大小,并使用 keepShortTerm (true/false )来控制是否保留原始术语。

您可以保留或不保留edge-ngram过滤器;看看它是否提高了结果的相关性?我怀疑如果您使用keepShortTerm = true,可能会稍微提高相关性。无论如何,请确保在 ngram 过滤器之前应用 edge-ngram 过滤器。

关于java - Hibernate搜索模糊超过2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61180101/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com