公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog2,发送下载链接帮助你免费下载!
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
本博客日IP超过2000,PV 3000 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog2,之前的微信号好友位已满,备注:返现
受密码保护的文章请关注“业余草”公众号,回复关键字“0”获得密码
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序

腾讯云】1核2G5M轻量应用服务器50元首年,高性价比,助您轻松上云
在 Lucene 中,不仅 TokenFilter 我们可以自定义,Analyzer 我们也可以自定义。本文介绍两个扩展 Analyzer 的例子,分别实现扩展停用词,实现字长过滤的功能。
自定义 Analyzer
自定义 Analyzer 只需要做到下面 3 步即可。
- 继承自 Analyzer 并覆写 createComponents(String) 方法
- 维护自己的停用词词典
- 重写 TokenStreamComponents,选择合适的过滤策略
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | 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 实现字长过滤。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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 是一个抽象类,它要这样的设计其实就是一个装饰器模式,方便我们扩展!
学习一个新的框架,照葫芦画瓢可能是最快捷的方式!
最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加作者微信号:xttblog2。备注:“1”,添加博主微信拉你进微信群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作也可添加作者微信进行联系!
本文原文出处:业余草: » Lucene 实战教程第九章自定义 Analyzer