1.简述
分析(analysis),在lucene中指的是将域(Field)转换成最基本的索引表示单元——项(Term)的过程。项的值称为语汇单元(token)。
对于英文来说,这个过程历经了提取单词、去除标点、字母转小写、去除停用词、词干还原等。
对应关系见图1-1.
图1-1 field与term的对应关系图示
2.Analyzer
Analyzer
抽象类。
lucene内置有WhitespaceAnalyzer、SimpleAnalyzer、StopAnalyzer与StandardAnalyzer等分析器。
2.1 StandardAnalyzer简介
StandardAnalyzer
这是lucene最复杂的核心分析器。它包含大量的逻辑操作来识别某些种类的语汇单元(token),比如公司名称、email地址等。它的主要处理有:提取单词、去除标点、字母转小写、去除停用词。
StandardAnalyzer的createComponents()方法见下:
@Override
protected TokenStreamComponents createComponents(final String fieldName) {
final StandardTokenizer src = new StandardTokenizer();
src.setMaxTokenLength(maxTokenLength);
TokenStream tok = new StandardFilter(src);
tok = new LowerCaseFilter(tok);
tok = new StopFilter(tok, stopwords);
return new TokenStreamComponents(src, tok) {
@Override
protected void setReader(final Reader reader) {
src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
super.setReader(reader);
}
};
}
可以清晰的看到分析过程就是 reader->tokenizer->tokenfilter_0->...->tokenfilter_n->tokens.
2.2 指定分析器
在创建IndexWriter时,会指定默认的分析器。也可以在addDocument()与updateDocument()的时候单独为某个文档指定特殊的分析器。
2.3 索引与查询两个阶段的分析器使用
QueryParser通过解析用户输入的lucene查询语法来生成Query对象,为用户带来了方便。
2.4 相关方法
Analyzer
抽象类。分析器,用于从域(field)中构建语汇单元(tokenstream)。
TokenStream org.apache.lucene.analysis.Analyzer. tokenStream(String fieldName, String text)
它会调用createComponents()方法获得 TokenStreamComponents实例,然后返回components.getTokenStream()结果。
TokenStream org.apache.lucene.analysis.Analyzer. tokenStream(String fieldName, Reader reader)
tokenStream()的重载方法。
createComponents(String fieldName)
创建这个analyzer的component。内部会set reader,set tokenizer,set 若干个tokenfilter。
2.4.1 TokenStreamComponents
org.apache.lucene.analysis.Analyzer. TokenStreamComponents
内部静态类。它封装了一个tokenstream的外部组件。它提供了对tokenizer的访问。
TokenStreamComponents(Tokenizer source, TokenStream result)
构造函数。
TokenStream org.apache.lucene.analysis.Analyzer.TokenStreamComponents. getTokenStream()
此方法被Analyzer.tokenStream()方法调用。
2.5 自定义Analyzer
继承Analyzer这个抽象类,重写createComponents方法即可。
createComponents(String fieldName)
抽象方法,要求子类重写。
一个filter链中,不能随意调整tokenFilter的顺序。例如StopFilter对停用词是区分大小写的,那么将它置于LowerCaseFilter的前面与后面结果是不一样的。
在指定filter顺序时,还要考虑对程序性能的影响。例如我们要考虑这样一个分析器,它既能移除停用词,又能将同义词注入到语汇单元流中。此时,首先移除停用词效果会高一点,避免不必要的计算。
2.6 测试Analyzer
在索引过程中,是看不到field在背后被怎样分析的,我们可以在测试方法中直接new Analyzer对象来测试文本的分析效果。
示例工程 :
3.TokenStream
TokenStream
抽象类,具体的子类有Tokenizer与TokenFilter。
boolean org.apache.lucene.analysis.TokenStream. incrementToken()
移动游标,得到下一个token,如果tokenstream消费完了返回false。类似JDBC的ResultSet.hasNext()。
void org.apache.lucene.analysis.TokenStream. reset()
在开始调用incrementToken()方法前要先调用此方法。
3.1 TokenNizer
Tokenizer
抽象类。TokenStream的子类,输入为reader对象。
setReader(Reader input)
设置Tokenizer的reader。
3.2 TokenFilter
TokenFilter
抽象类,TokenStream的子类,输入为其他的tokenstream对象,可用于迭代链式过滤。常见的子类有LowerCaseFilter,StopFilter等。
TokenFilter(TokenStream input)
构造函数,由子类通过super()方式调用,传入Tokenizer对象或tokenFilter对象。
LowerCaseFilter
将token中的字母转为小写。
org.apache.lucene.analysis.core. StopFilter
移除停用词。
PorterStemFilter
基于波特算法的词干过滤器。StandardAnalyzer没有用它,但我们自己可以方便地写一个Analyzer来用它。
3.3 TokenAttribute
TokenStream在得到token(语汇单元)的时候,并不会创建string来保存token,而是通过维护token在stream中的偏移位置来实现。
3.3.1 CharTermAttribute
CharTermAttribute
接口。代表token的text属性。
org.apache.lucene.analysis.tokenattributes. CharTermAttributeImpl
CharTermAttribute接口的实现类。
String org.apache.lucene.analysis.tokenattributes.CharTermAttributeImpl. toString()
输出代表token的text。
3.3.2 OffsetAttribute
OffsetAttribute
接口。描述一个token在stream中的偏移位置(起始字符与终止字符)。