簡體   English   中英

Hibernate 搜索模糊2個以上

[英]Hibernate search fuzzy more than 2

我有一個 Java 后端,帶有 hibernate、lucene 和休眠搜索。 現在我想做一個模糊查詢,但不是 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-gram。 我不是在談論邊緣 ngram,就像你已經做過的那樣,而是從整個術語中提取的實際 ngram,而不僅僅是邊緣。 因此,當索引 2 克foooo時,您將索引:

  • fo
  • oo (出現多次)

在查詢時,術語fouuu將轉換為:

  • fo
  • ou
  • uu

...並且它將匹配索引文檔,因為它們至少有一個共同的術語( fo )。

顯然有一些缺點。 對於 2-gram,術語fuuuu不會匹配foooo ,但術語barfooo會匹配,因為它們有一個 2-gram 的共同點。 所以你會得到誤報。 克數越長,您獲得誤報的可能性就越小,但您的搜索就越模糊。

您可以依靠得分和按得分排序將最佳匹配項放在結果列表中的首位,從而使這些誤報 go 消失。 例如,您可以配置 ngram 過濾器以保留原始術語,這樣fooo將被轉換為 [ fooo , fo , oo ] 而不僅僅是 [ fo , oo ],因此精確搜索fooo會有更好的分數對於包含fooo barfooo文檔(因為匹配項更多)。 您還可以設置多個單獨的字段:一個不帶 ngram,一個帶 3-gram,一個帶 2-gram,並構建一個 boolean 查詢,每個字段都帶有 on should子句:匹配的子句越多,得分越高,並且您會在點擊中找到更高的文檔。

另外,我認為fooo和類似的東西確實是人為的例子,你不太可能在現實世界的數據集中擁有這些術語; 您應該嘗試針對真實數據集提出的任何解決方案,看看它是否足夠好。 如果你想要模糊搜索,你將不得不接受一些誤報:問題不在於它們是否存在,而在於它們是否足夠稀有以至於用戶仍然可以輕松找到他們正在尋找的東西。

為了使用 ngram,請使用org.apache.lucene.analysis.ngram.NGramFilterFactory應用 n-gram 過濾器。 在索引和查詢時都應用它。 使用參數minGramSize / maxGramSize配置 ngram 的大小,並keepShortTerm ( true / false ) 控制是否保留原始術語。

您可以保留或不保留 edge-ngram 過濾器; 看看它是否提高了結果的相關性? 我懷疑如果您使用keepShortTerm = true可能會稍微提高相關性。 在任何情況下,請確保在 ngram 過濾器之前應用 edge-ngram 過濾器。

好的,我和我的朋友找到了解決方案。 我們在 lucene 的變更日志中發現了一個要求相同功能的問題,我們實施了一個解決方案SlowFuzzyQuery的沙盒版本中有一個 SlowFuzzyQuery。 它速度較慢(顯然),但支持大於 2 的 editDistance。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM