2016-07-29 49 views
2

我已經實現了一個基於lucene的軟件來索引超過1000萬人的名字,這些名字可以用「Luíz」和「Luis」等不同的方式編寫。索引是使用相應令牌的語音值創建的(自定義分析器已創建)。我們可以在拼音索引中使用SpanNearQuery嗎?

目前,我正在使用QueryParser來查詢給定的名字並獲得好的結果。但是,在「Lucene in Action」一書中提到,SpanNearQuery可以使用標記的接近度來改進我的查詢。我已經使用SpanNearQuery針對名稱的非語音索引,結果比QueryParser更好。

我們應該查詢使用與索引相同的分析,我找不到我怎麼能在同一時間使用個性化的語音分析和SpanNearQuery,或改:提前

how can I use SpanNearQuery on the phonetic index? 

感謝。

回答

1

我的第一個想法是:不會使用slop的詞組查詢工作嗎?這當然是最簡單的方法:

"term1 term2"~5 

這將使用您的語音分析器,併產生一個接近查詢與結果令牌。


所以,如果你真的必要在這裏使用SpanQueries(也許你正在使用模糊查詢或通配符或一些這樣或PhraseQuery已經在你惡狠狠送秋波,你想沒有什麼用它做),你需要自己做分析。您可以通過從Analyzer.tokenStream獲取TokenStream並遍歷分析的令牌來完成此操作。

如果使用一個語音算法產生每術語單個代碼(同音,例如):

SpanNearQuery.Builder nearBuilder = new SpanNearQuery.Builder("text", true); 
nearBuilder.setSlop(4); 

TokenStream stream = analyzer.tokenStream("text", queryStringToParse); 
stream.addAttribute(CharTermAttribute.class); 
stream.reset(); 
while(stream.incrementToken()) { 
    CharTermAttribute token = stream.getAttribute(CharTermAttribute.class); 
    nearBuilder.addClause(new SpanTermQuery(new Term("text", token.toString()))); 
} 
Query finalQuery = nearBuilder.build(); 
stream.close(); 

如果使用雙音位,在這裏可以具有在1-2術語相同的位置,它有點複雜,因爲您需要考慮這些位置增量:

SpanNearQuery.Builder nearBuilder = new SpanNearQuery.Builder("text", true); 
nearBuilder.setSlop(4); 

TokenStream stream = analyzer.tokenStream("text", "through and through"); 
stream.addAttribute(CharTermAttribute.class); 
stream.addAttribute(PositionIncrementAttribute.class); 
stream.reset(); 
String queuedToken = null; 
while(stream.incrementToken()) { 
    CharTermAttribute token = stream.getAttribute(CharTermAttribute.class); 
    PositionIncrementAttribute increment = stream.getAttribute(PositionIncrementAttribute.class); 

    if (increment.getPositionIncrement() == 0) { 
     nearBuilder.addClause(new SpanOrQuery(
       new SpanTermQuery(new Term("text", queuedToken)), 
       new SpanTermQuery(new Term("text", token.toString())) 
       )); 
     queuedToken = null; 
    } 
    else if (increment.getPositionIncrement() >= 1 && queuedToken != null) { 
     nearBuilder.addClause(new SpanTermQuery(new Term("text", queuedToken))); 
     queuedToken = token.toString(); 
    } 
    else { 
     queuedToken = token.toString(); 
    } 
} 

if (queuedToken != null) { 
    nearBuilder.addClause(new SpanTermQuery(new Term("text", queuedToken))); 
} 

Query finalQuery = nearBuilder.build(); 
stream.close(); 
相關問題