2013-08-07 79 views
9

我正在尋找一種對lucene模糊查詢進行編碼的方法,它可以搜索與精確短語相關的所有文檔。如果我搜索「莫薩員工欣賞」,那麼包含「大多數員工欣賞」的文檔將作爲結果返回。Lucene在一個短語上進行模糊搜索(FuzzyQuery + SpanQuery)

我試着使用:

FuzzyQeury = new FuzzyQuery(new Term("contents","mosa employee appreicata")) 

不幸的是,經驗是行不通的。 FuzzyQuery應用編輯距離,理論上講,「莫薩員工欣賞」應該與「大多數員工欣賞」相匹配,並給出適當的距離。這似乎有點奇怪。

任何線索?謝謝。

+0

需要額外的詳細信息:您是如何爲內容字段編制索引的?你在用什麼分析儀?您是否嘗試過更近距離的搜索(從確切的詞組開始,然後更改單個字符,...)?你在查詢參數中給了多少緯度?你究竟得到了什麼? –

回答

1

femtoRgon的答案很棒!謝謝。

還有另一種方法可以解決這個問題。

//declare a mutilphrasequery 
MultiPhraseQuery childrenInOrder = new MultiPhraseQuery(); 

//user fuzzytermenum to enumerate your query string 
FuzzyTermEnum fuzzyEnumeratedTerms1 = new FuzzyTermEnum(reader, new Term(searchField,"mosa")); 
FuzzyTermEnum fuzzyEnumeratedTerms2 = new FuzzyTermEnum(reader, new Term(searchField,"employee")); 
FuzzyTermEnum fuzzyEnumeratedTerms3 = new FuzzyTermEnum(reader, new Term(searchField,"appreicata")); 

//this basically pull out the possbile terms from the index    
Term termHolder1 = fuzzyEnumeratedTerms1.term(); 
Term termHolder2 = fuzzyEnumeratedTerms2.term(); 
Term termHolder3 = fuzzyEnumeratedTerms3.term(); 

//put the possible terms into multiphrasequery 
if (termHolder1==null){ 
    childrenInOrder.add(new Term(searchField,"mosa")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms1.term()); 
} 

if (termHolder2==null){ 
    childrenInOrder.add(new Term(searchField,"employee")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms2.term()); 
} 

if (termHolder3==null){ 
    childrenInOrder.add(new Term(searchField,"appreicata")); 
}else{ 
    childrenInOrder.add(fuzzyEnumeratedTerms3.term()); 
} 


//close it - it is important to close it 
fuzzyEnumeratedTerms1.close(); 
fuzzyEnumeratedTerms2.close(); 
fuzzyEnumeratedTerms3.close(); 
+3

你使用了什麼版本的lucene?我似乎無法找到4.6的FuzzyTermEnum api。在4.6只有FuzzyTermsEnum與不同的構造函數 – nir

+0

恕我直言,這實際上並沒有做你想要的。也許是你的簡單例子,但不適用於更多文本更復雜的文檔。由於FuzzyTermEnum沒有爲索引中的較大文檔提供正確的條款...... –

11

這裏有兩個可能的問題。首先:我在猜測「內容」字段正在被分析,以至於「大多數員工都會說」不是一個術語,而是三個術語。在這種情況下,定義爲單個術語並不合適。

但是,即使列出的內容是單個術語,但我們可能遇到的第二個問題是術語之間的距離太大以致無法匹配。 mosa employee appreicatamost employees appreciate之間的Damerau-Levenshtein距離是4(順便說一下,我在拼寫爲 「Damerau-Levenshtein」的平均第一次投射和正確拼寫之間的近似距離)。從4.0開始,模糊查詢處理的編輯距離不超過2,這是由於性能限制,以及較大距離通常不是特別相關的假設。

如果您需要執行的模糊條款短語查詢,你應該考慮要麼MultiPhraseQuery,或結合了一套SpanQueries(尤其是SpanMultiTermQueryWrapperSpanNearQuery),以滿足您的需求。

SpanQuery[] clauses = new SpanQuery[3]; 
clauses[0] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "mosa"))); 
clauses[1] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "employee"))); 
clauses[2] = new SpanMultiTermQueryWrapper(new FuzzyQuery(new Term("contents", "appreicata"))); 
SpanNearQuery query = new SpanNearQuery(clauses, 0, true) 

而且由於沒有一個單獨的術語的編輯距離大於2,這應該更有效。

+0

使用Lucene查詢語言可以實現同樣的功能嗎? – isah

+0

@isah - 你的意思是標準的QueryParser? *你不能。 [ComplexPhrase解析器](https://lucene.apache.org/core/5_5_0/queryparser/org/apache/lucene/queryparser/complexPhrase/ComplexPhraseQueryParser.html)可以... – femtoRgon

+0

是的,我剛剛用ComplexQueryParser完成它問你,謝謝。 – isah