lucene如何写自己的同义词分词器
前一篇文章 lucene分词流程讲解了分词的一些流程,我们也对分词流程有了一个初步的了解,知道一个分词器由多个Tokenizer和TokenFilter组成,这篇文章讲解的就是我们利用这两个特性实现自己的一个简单的同义词分词器,不妥之处请大家指出
(一)分析
如何实现同义词呢?比如重庆可以叫做山城,我们搜索山城的时候也应该要搜索要包含重庆这个单词的文章。那么我们就必须要了解lucene只怎么处理我们的文档了,上一篇说了在一篇文档当中lucene给一段话赋予了3个类。这3个类记录了每一个词语的偏移量,位置增量等等。lucene通过位置增量来判断位置,那么我们现在是否有自己的想法了呢。我们只要在相应的位置加上自己的同义词就ok了
(二)实现
那么首先我们要实现一个自己的analazer,覆盖tokenSTREAM方法(因为我们要自定义一个filter,stream流要改变)
package org.xiezhaodong.lucene; import java.io.Reader; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.WhitespaceTokenizer; import org.apache.lucene.util.Version; public class MySameAnalyzer extends Analyzer { @Override public TokenStream tokenStream(String arg0, Reader arg1) { return new MySameFilter(new WhitespaceTokenizer(Version.LUCENE_35, arg1));//调用自己实现的filter,分词器我们用空格分词器就可以了 } }
package org.xiezhaodong.lucene; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Stack; import org.apache.lucene.analysis.TokenFilter; import org.apache.lucene.analysis.TokenStream; import org.apache.lucene.analysis.tokenattributes.CharTermAttribute; import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute; import org.apache.lucene.util.AttributeSource; public class MySameFilter extends TokenFilter { private CharTermAttribute cta=null;//要得到词汇就要得到这个,上一篇已经讲到 private Stack<String> wordStack=null;//存放同义词的stack private AttributeSource.State current=null; private PositionIncrementAttribute pia;//位置增量设置 protected MySameFilter(TokenStream input) { super(input); wordStack=new Stack<String>(); pia=this.addAttribute(PositionIncrementAttribute.class);//从tokenStream中得到这两个关键类 cta=this.addAttribute(CharTermAttribute.class); } @Override public boolean incrementToken() throws IOException { while(wordStack.size()>0){ String word=wordStack.pop(); restoreState(current);//还原到上一个状态 cta.setEmpty(); cta.append(word); pia.setPositionIncrement(0);//增量为0和原单词相对相同 return true; } if(!this.input.incrementToken())return false; if(isHaveSameWords(cta.toString())){//有同义词 current=captureState();//捕获当前状态,上一节说了,可以捕获当前流的状态 } return true; } //判断该词语是否有同义词,这里我们假设这些同义词,我乱写的 public boolean isHaveSameWords(String word){ Map<String, String[]> map=new HashMap<String, String[]>(); map.put("how", new String[]{"what","which"}); map.put("thank", new String[]{"like","love"}); String[] sws=map.get(word); if(sws!=null){ //存在同义词 for(String s:sws){ wordStack.push(s); } return true; } return false; } }
测试工具类
public class AnalyzerUtils { public static void displayAllTokenInfo(String str, Analyzer a) { try { TokenStream tokenStream = a.tokenStream("content", new StringReader(str)); PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class); OffsetAttribute oa = tokenStream.addAttribute(OffsetAttribute.class); CharTermAttribute cta = tokenStream.addAttribute(CharTermAttribute.class); TypeAttribute ta = tokenStream.addAttribute(TypeAttribute.class); while(tokenStream.incrementToken()){ //System.out.print(positionIncrementAttribute.getPositionIncrement()); System.out.print(cta+"{"+oa.startOffset()+"-"+oa.endOffset()+"}"); } System.out.println(); } catch (Exception e) { e.printStackTrace(); } } }
@Test public void test04(){ // Analyzer analyzer=new StandardAnalyzer(Version.LUCENE_35); //Analyzer analyzer2=new StopAnalyzer(Version.LUCENE_35); // Analyzer analyzer3=new SimpleAnalyzer(Version.LUCENE_35); // Analyzer analyzer4=new WhitespaceAnalyzer(Version.LUCENE_35); //Analyzer analyzer=new MyStopAnalyzer(new String[]{"I","you"}); Analyzer analyzer=new MySameAnalyzer(); String txt="how are you thank you"; // AnalyzerUtils.displayToken(txt, analyzer); AnalyzerUtils.displayAllTokenInfo(txt, analyzer); }
how{0-3}which{0-3}what{0-3}are{4-7}you{8-11}thank{12-17}love{12-17}like{12-17}you{18-21}有没有发现,同义词已经加进去了,而且他们的偏移量和位置增量都是一样的,然后我们搜索what的时候就可以把这篇文档搜索出来了。具体就不演示了,下面有附件,自行下载试一试,当然除了实现同义词,我们只要知道了怎么自定义自己的filter可tokenizer我们可以做很多的事情。
转载请注明http://blog.csdn.net/a837199685/article/
附件链接http://pan.baidu.com/s/1o6n2O9k
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。