我正在尝试使用apache Lucene 5.5.4
为给定的一组输入文本生成N-gram。以下是我执行相同操作的Java代码。
public static void main( String[] args )
{
Analyzer analyzer = createAnalyzer( 2 );
List<String> nGrams = generateNgrams( analyzer,"blah1 blah2 blah3" );
for ( String nGram : nGrams ) {
System.out.println( nGram );
}
}
public static Analyzer createAnalyzer( final int shingles )
{
return new Analyzer() {
@Override
protected TokenStreamComponents createComponents( @NotNull String field )
{
final Tokenizer source = new WhitespaceTokenizer();
final ShingleFilter shingleFilter = new ShingleFilter( new LowerCaseFilter( source ),shingles );
shingleFilter.setOutputUnigrams( true );
return new TokenStreamComponents( source,shingleFilter );
}
};
}
public static List<String> generateNgrams( Analyzer analyzer,String str )
{
List<String> result = new ArrayList<>();
try {
TokenStream stream = analyzer.tokenStream( null,new StringReader( str ) );
stream.reset();
while ( stream.incrementToken() ) {
String nGram = stream.getattribute( CharTermAttribute.class ).toString();
result.add( nGram );
LOG.debug( "Generated N-gram = {}",nGram );
}
} catch ( IOException e ) {
LOG.error( "IO Exception occured! {}",e );
}
return result;
}
对于我的输入blah1 blah2 blah3
,输出如下,我可以接受。
blah1
blah1 blah2
blah2
blah2 blah3
blah3
但是,当输入为Foo bar Foo2
时,我的要求是生成以下输出:
-
Foo
-
Foo bar
-
bar
-
bar Foo2
-
Foo2
如果您注意到了,我必须在输入中保留两个单词之间的空格(Foo bar
,而不是Foo bar
)。
我可以进行任何调整,并要求Lucene在内部进行处理吗?
可能是一个小的调整,例如添加过滤器之类的东西,由于我是Lucene的新手,所以我不知道从哪里开始。 预先感谢。
编辑1
调试Lucene源代码后,我发现在代码中附加了带状疱疹。
if (builtGramSize < gramNum) {
if (builtGramSize > 0) {
gramBuilder.append(tokenSeparator);
}
gramBuilder.append(nextToken.termAtt.buffer(),nextToken.termAtt.length());
++builtGramSize;
}
gramBuilder.append(tokenSeparator)
是将非令牌(分隔符)附加到输出N-gram的位置。上面的代码是在ShingleFilter.class
和incrementToken()
方法中找到的。