2010-04-13 37 views
10

在Lucene的查詢語法,我想結合*和〜類似有效的查詢: BLA〜* //無效的查詢Lucene查詢:bla〜*(匹配的單詞以模糊的東西開頭),怎麼樣?

含義:請匹配以「喇嘛」開頭的單詞或類似的東西「喇嘛」。

更新: 我現在所做的工作,適用於小的輸入,是使用以下(SOLR模式的片段):

<fieldtype name="text_ngrams" class="solr.TextField"> 
    <analyzer type="index"> 
     <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
     <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
     <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/> 
    </analyzer> 
    <analyzer type="query"> 
     <tokenizer class="solr.WhitespaceTokenizerFactory"/> 
     <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/> 
     <filter class="solr.LowerCaseFilterFactory"/> 
    </analyzer> 

如果你不使用SOLR,這做了以下。

索引時間:通過創建包含我的(短)輸入的所有前綴的字段索引數據。

搜索時間:僅使用〜運算符,因爲索引中明確存在前綴。

回答

2

我不相信Lucene支持這樣的事情,我也不相信它有一個微不足道的解決方案。

「模糊」搜索不會對固定數量的字符進行操作。例如bla~可以匹配blah,因此它必須考慮整個術語。

你可以做的是實現一個拿着查詢bla~*,並把它轉換成一系列或查詢

bla* OR blb* OR blc OR .... etc. 

查詢擴展算法但是,這確實是唯一可行的,如果字符串很短,或者如果您可以根據一些規則縮小擴展範圍。

或者,如果前綴的長度是固定的,您可以添加一個字段與子字符串並對其執行模糊搜索。這會給你你想要的,但只會在你的用例足夠窄的時候纔會起作用。

你沒有確切地說明你爲什麼需要這個,也許這樣做會引出其他解決方案。

我能想到的一種情況是處理不同形式的單詞。例如。找到carcars

這是很容易的英文,因爲有詞幹提供。在其他語言中,如果不是不可能的話,實施詞幹分析者可能相當困難。

然而,在這種情況下,您可以(假設您有權訪問一本好字典)查找搜索詞並以編程方式展開搜索以搜索該詞的所有形式。

E.g.搜索cars被翻譯成car OR cars。至少在一個搜索引擎中,這已經成功地應用於我的語言,但顯然不是很容易實現。

+0

Althoug模糊搜索不會在一個固定數目的字符操作,我的情況簡單地使用〜(以字符數爲大差異)不會工作。我想匹配例如Sunla到Sundlaugarvegur。 – 2010-04-13 19:56:14

+0

當然,如果我能告訴lucene只匹配索引中每個單詞的前x個字符,使用〜會工作... – 2010-04-13 20:04:07

+0

你需要超越Lucene在這裏,使用字符串比較算法,如Levenstein,Jaro -Winkler etc.(qv。below) – Mikos 2010-04-14 13:33:08

0

你的意思是你想結合通配符和模糊查詢?你可以使用一個布爾查詢與OR條件結合起來,例如:

BooleanQuery bq = new BooleanQuery(); 

Query q1 = //here goes your wildcard query 
bq.Add(q1, BooleanClause...) 

Query q2 = //here goes your fuzzy query 
bq.Add(q2, BooleanClause...) 
+0

我不相信這會完成OP所要求的,因爲它基本上會變成「bar〜OR bar *」,它與「bar〜*」不同,並且不會找到(例如)「brafoo」。 – Kris 2010-04-13 16:52:52

+0

是的,這不是我想要的:) – 2010-04-13 20:03:23

+0

好的,謝謝澄清,我用過的一種方法(用於匹配蛋白質等名稱)使用像Smith-Waterman,Jaro-Winkler等字符串距離等。SimMetrics等工具可能有一定的幫助 http://www.dcs.shef.ac.uk/~sam/simmetrics.html – Mikos 2010-04-14 13:31:30

1

這是一個地址搜索服務,在這裏我想建議基於地址部分類型和可能的錯誤輸入街道名稱/ citynames的/ etc(任組合)。 (想AJAX,用戶鍵入的文本字段部分街道地址)

對於這種情況,建議查詢擴展也許不是那麼可行,因爲部分字符串(街道地址)可能會變得長於「短」 :)

歸我能想到的

一種可能性是使用字符串「正常化」,而不是模糊搜索,並簡單地結合起來,與通配符查詢。街道地址

"miklabraut 42, 101 reykjavík",歸一化時將變爲"miklabrat 42 101 rekavik"

因此,建築指數這樣

1)建立與含街道名稱,城市名稱等的「正常化」的版本記錄索引,每個文件(1個或幾個領域一個街道地址)。

和搜索這樣指數:

2)歸一化inputstrings(例如mikl reyk)用於形成查詢(即mik rek)。 3)使用通配符op來執行搜索(即mik* AND rek*),留下模糊部分。

這將飛翔,提供標準化的算法是在Lucene的發展幹線(尚未釋放)足夠好:)

7

,有代碼來支持的用例這樣,通過AutomatonQuery。警告:API在發佈之前可能會/會發生變化,但它給了你這個想法。

這裏是你的情況的一個例子:

// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such 
Term term = new Term("yourfield", "bla~*"); 

// builds a DFA that accepts all strings within an edit distance of 2 from "bla" 
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2); 

// concatenate this DFA with another DFA equivalent to the "*" operator 
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString()); 

// build a query, search with it to get results. 
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix); 
+0

我剛回到這個問題,並再次看到你的答案。你試過了嗎?我現在所做的(適用於小輸入)是爲了生成所有輸入的前綴並將前綴放在索引中。然後,我只需要使用〜運算符,並獲得像〜* – 2010-12-01 10:29:53

+0

這樣的功能。對於小輸入,您的解決方法就好了......但正如您所暗示的那樣,對於大型輸入來說會是一個問題:您將添加大量術語,所有這些前綴的發佈......這將使Lucene 4.0之前的模糊查詢更慢,因爲它對所有術語進行線性掃描。 – 2010-12-21 01:31:44

+0

是否有一個Lucene查詢語法,可讓您通過Solr訪問Automaton查詢而無需編碼? – wrschneider 2013-05-01 17:50:40

相關問題