2016-07-29 73 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(); 
相关问题