在 Lucene 中,不仅 TokenFilter 我们可以自定义,Analyzer 我们也可以自定义。本文介绍两个扩展 Analyzer 的例子,分别实现扩展停用词,实现字长过滤的功能。
自定义 Analyzer
自定义 Analyzer 只需要做到下面 3 步即可。
- 继承自 Analyzer 并覆写 createComponents(String) 方法
- 维护自己的停用词词典
- 重写 TokenStreamComponents,选择合适的过滤策略
class StopAnalyzerExtend extends Analyzer {
private CharArraySet stopWordSet;//停止词词典
public CharArraySet getStopWordSet() {
return this.stopWordSet;
}
public void setStopWordSet(CharArraySet stopWordSet) {
this.stopWordSet = stopWordSet;
}
public StopAnalyzerExtend() {
super();
setStopWordSet(StopAnalyzer.ENGLISH_STOP_WORDS_SET);
}
/**
* @param stops 需要扩展的停止词
*/
public StopAnalyzerExtend(List<String> stops) {
this();
/**如果直接为stopWordSet赋值的话,会报如下异常,这是因为在StopAnalyzer中
有ENGLISH_STOP_WORDS_SET = CharArraySet.unmodifiableSet(stopSet);
* ENGLISH_STOP_WORDS_SET 被设置为不可更改的set集合
* Exception in thread "main" java.lang.UnsupportedOperationException
* at org.apache.lucene.analysis.util.CharArrayMap$UnmodifiableCharArrayMap.put(CharArrayMap.java:592)
* at org.apache.lucene.analysis.util.CharArraySet.add(CharArraySet.java:105)
* at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
* at MyAnalyzer.<init>(AnalyzerDemo.java:146)
* at MyAnalyzer.main(AnalyzerDemo.java:162)
*/
//stopWordSet = getStopWordSet();
stopWordSet = CharArraySet.copy(getStopWordSet());
stopWordSet.addAll(StopFilter.makeStopSet(stops));
}
@Override
protected TokenStreamComponents createComponents(String fieldName) {
Tokenizer source = new LowerCaseTokenizer();
return new TokenStreamComponents(source, new StopFilter(source, stopWordSet));
}
public static void main(String[] args) throws IOException {
ArrayList<String> strings = new ArrayList<String>() {{
add("小鬼子");
add("美国佬");
}};
Analyzer analyzer = new StopAnalyzerExtend(strings);
String content = "小鬼子 and 美国佬 are playing together!";
TokenStream tokenStream = analyzer.tokenStream("myfield", content);
tokenStream.reset();
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
while (tokenStream.incrementToken()) {
// 已经过滤掉自定义停用词
// 输出:playing together
System.out.println(charTermAttribute.toString());
}
tokenStream.end();
tokenStream.close();
}
}
扩展停用词可以过滤掉一些敏感词。
下面我们在来看另外一个例子。自定义 Analyzer 实现字长过滤。
class LongFilterAnalyzer extends Analyzer {
private int len;
public int getLen() {
return this.len;
}
public void setLen(int len) {
this.len = len;
}
public LongFilterAnalyzer() {
super();
}
public LongFilterAnalyzer(int len) {
super();
setLen(len);
}
@Override
protected TokenStreamComponents createComponents(String fieldName) {
final Tokenizer source = new WhitespaceTokenizer();
//过滤掉长度<len,并且>20的token
TokenStream tokenStream = new LengthFilter(source, len, 20);
return new TokenStreamComponents(source, tokenStream);
}
public static void main(String[] args) {
//把长度小于2的过滤掉,开区间
Analyzer analyzer = new LongFilterAnalyzer(2);
String words = "I am a java coder! Testingtestingtesting!";
TokenStream stream = analyzer.tokenStream("myfield", words);
try {
stream.reset();
CharTermAttribute offsetAtt = stream.addAttribute(CharTermAttribute.class);
while (stream.incrementToken()) {
System.out.println(offsetAtt.toString());
}
stream.end();
stream.close();
} catch (IOException e) {
}
}
}
自定义 Analyzer 要注意,Analyzer 里面的两个 tokenStream 方法是不能重写的。因为这两个方法是 final 方法,不能被覆盖的。
Analyzer 是一个抽象类,它要这样的设计其实就是一个装饰器模式,方便我们扩展!
学习一个新的框架,照葫芦画瓢可能是最快捷的方式!

: » Lucene 实战教程第九章自定义 Analyzer
原创文章,作者:Maggie-Hunter,如若转载,请注明出处:https://blog.ytso.com/tech/java/251965.html