最近做项目中应用到了Lucene做搜索应用,于是顺便学习它的源代码。下面就将学习到的“Lucene分析器分析过程”与大家分享!限于水平,错误难免。请大家不吝赐教。让拍砖来的更猛烈些,文章为原创,参照Lucen in Action中
部分内容,如需要转载,请与作者联系,或标明来源。谢谢!
一、先看看编写的Demo及运行效果,总览一下。
private static Log log = LogFactory.getLog(AnalyzerDemo.class);
public static void main(String[] args) throws IOException{
Analyzer analyzer = new SimpleAnalyzer();
TokenStream stream = analyzer.reusableTokenStream(null, new StringReader("Programminged is fun,by the way,do you like dog?"));
while(true){
Token token = stream.next();
if(null == token){
log.info("完毕!");
break;
}
log.info(new String(token.termBuffer()) + " 起始位置:" + token.startOffset() + " 结束位置:" + token.endOffset());
}
}
程序运行后控制台效果:
0 [main] INFO test.lucene.AnalyzerDemo - programminged 起始位置:0 结束位置:13
16 [main] INFO test.lucene.AnalyzerDemo - is 起始位置:14 结束位置:16
16 [main] INFO test.lucene.AnalyzerDemo - fun 起始位置:17 结束位置:20
16 [main] INFO test.lucene.AnalyzerDemo - by 起始位置:21 结束位置:23
16 [main] INFO test.lucene.AnalyzerDemo - the 起始位置:24 结束位置:27
16 [main] INFO test.lucene.AnalyzerDemo - way 起始位置:28 结束位置:31
16 [main] INFO test.lucene.AnalyzerDemo - do 起始位置:32 结束位置:34
16 [main] INFO test.lucene.AnalyzerDemo - you 起始位置:35 结束位置:38
16 [main] INFO test.lucene.AnalyzerDemo - like 起始位置:39 结束位置:43
16 [main] INFO test.lucene.AnalyzerDemo - dog 起始位置:44 结束位置:47
16 [main] INFO test.lucene.AnalyzerDemo - 完毕!
以上代码中,使用SimpleAnalyzer进行分析。它内置使用LowerCaseTokenizer 。至于分析的结果,我将在下文结合Lucene源代码详细描述。
二、让我们看一下UML图,UML图画的可能比较粗糙一些
这个图是SimpleAnalyzer的架构图,旁边给了说明,就不再赘述了。值的注意的是,simpleAnalyzer两个方法,返回值都是TokenStream,这个类就是我刚才提到的LowerCaseTokenizer的超类。
为了方便大家观看它的结构。下面将给出它的架构图,如下:
三、分析处理过程
上述代码中,我们构建了一个LowerCaseTokenizer,通过构造方法,将StringReader传递到Tokeinzer的 protected Reader input 中。
接着调用TokenStrem的next()方法,这个方法主要是构建Token的,在这个方法内部,它调用CharTokenizer的重载方法,下面主要讲讲Chartokenizer.next(Token token)
1)程序给出了一个死循环,while(true),在这个循环内部,逐个调字串分析,调用抽象方法isTokenChar,如果返回false,则break循环。我们上例中,碰到“空格”后就跳出。
2)如果是字符串,即时isTokenChar返回为真的时候,记录下这个字串到char[] buffer中。
3)char[] buffer在初始化时,设置长度为10,如果超出10,比如我们的"Programminged"(为了超出10个字串,说明问题,构建了一个错误的单词,见笑了。)则扩充长度*2
这段代码在Token中,size *= 2;
char[] newBuffer = new char[size];
System.arraycopy(termBuffer, 0, newBuffer, 0, termBuffer.length);
4)包装Token,内容不但有每个Token的内容,还有它的起始、结束位置。谓之原数据。这将在高亮显示时使用。
四、Analyzer将输入源进行分析,通过DocumentsWriter进行写索引。
见代码:
// Tokenize field and add to postingTable
stream = analyzer.reusableTokenStream(fieldInfo.name, reader);
上述是Lucene自带的SimpleAnalyzer分析处理过程,我们可以扩充Analyzer 类,扩建自已的中文分词处理器。