好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

lucene 的分析器(analyzer)与分词器(tokenizer)和过滤器(tokenfilt

lucene 的分析器(analyzer)与分词器(tokenizer)和过滤器(tokenfilter)

作者:1987(lianj_lee)
HdhCmsTestdzxiaoshuo测试数据

好久没有写博客了,最近确实是有点忙。这几天在给IK做测试,很高兴,我能为IK做贡献,希望以后能继续。

正是由于给做测试工作,所以我就把关于lucene的分析器,过滤器和分词器这些东西温习了下,然后希望这个博客能给大家带来一定帮助。

还有我想从今天声明一下,欢迎大家转载我的博客,我希望给越来越多的人带来帮助,但是请务必注明作者, 1987(lianj_lee)

入正题:

1〉analyzer主要包含分词器跟过滤器,他的功能就是:将分词器跟分析器进行合理的组合,使之产生对文本分词和过滤效果。因此,分析器使用分词和过滤器构成一个管道,文本在“滤过”这个管道之后,就成为可以进入索引的最小单位。
2〉tokenizer主要用于对文本资源进行切分,将文本规则切分为一个个可以进入索引的最小单元
3〉tokenfilter主要对分词器切分的最小单位进入索引进行预处理,如:大写转小写,复数转单数,也可以复杂(根据语义改写拼写错误的单词)

附上lucene的部分类源码以讲解:

 

Java代码  

public   abstract  TokenStream tokenStream(String fieldName, Reader reader); //该抽象为子分析器扩展,后面会在说到          public  TokenStream reusableTokenStream(String fieldName, Reader reader)  throws  IOException {        return  tokenStream(fieldName, reader);     } //这个是后来发行版本添加的,主要用途是:创建一个TokenStream,为了同一个线程重复使用,节省时间          private  CloseableThreadLocal tokenStreams =  new  CloseableThreadLocal(); // 利用ThreadLocal 来达到在同一个线程重复使用。 这种应用很普遍,例如hibernate的session也是这种情况          protected  Object getPreviousTokenStream() {        try  {          return  tokenStreams.get();       }  catch  (NullPointerException npe) {          if  (tokenStreams ==  null ) {            throw   new  AlreadyClosedException( "this Analyzer is closed" );         }  else  {            throw  npe;         }       }     }         protected   void  setPreviousTokenStream(Object obj) {        try  {         tokenStreams.set(obj);       }  catch  (NullPointerException npe) {          if  (tokenStreams ==  null ) {            throw   new  AlreadyClosedException( "this Analyzer is closed" );         }  else  {            throw  npe;         }       }     }         public   int  getPositionIncrementGap(String fieldName)     {        return   0 ;     }         public   void  close() {       tokenStreams.close();       tokenStreams =  null ;     }  


Java代码  

public  TokenStream tokenStream(String fieldName, Reader reader) {       StandardTokenizer tokenStream =  new  StandardTokenizer(reader, replaceInvalidAcronym);       tokenStream.setMaxTokenLength(maxTokenLength);       TokenStream result =  new  StandardFilter(tokenStream);       result =  new  LowerCaseFilter(result);       result =  new  StopFilter(result, stopSet);        return  result;     }  


StandardAnalyzer提供的实现,可以看到很简单,就是组合了分词跟过滤器,首先实例了StandardTokenizer(),然 后获得了tokenStream,将他传入过滤器,在这样的过程中,result没有发生任何改变,真正发生改变的是在建立索引或者搜索的时候,继续往下 看,

Java代码  

public  StandardTokenizer(Reader input,  boolean  replaceInvalidAcronym) {        this .replaceInvalidAcronym = replaceInvalidAcronym;        this .input = input;        this .scanner =  new  StandardTokenizerImpl(input);     }  



StandardTokenizerImpl的构造方法:

Java代码  

StandardTokenizerImpl(java.io.Reader in) {        this .zzReader = in;     }  



StartdFilter的构造方法:

Java代码  

public  StandardFilter(TokenStream in) {        super (in);     }  



当建立索引或者搜索的时候,会调用由tokenStream方法返回的TokenStream的next()方法,也是这个时候真正的分词和过滤就开始了。
接着看,当第一调用next()方法时候,首先应该进入StopFilter的next,因为result = new StopFilter(result, stopSet);

Java代码  

public   final  Token next( final  Token reusableToken)  throws  IOException {        assert  reusableToken !=  null ;        // return the first non-stop word found         int  skippedPositions =  0 ;        for  (Token nextToken = input.next(reusableToken); nextToken !=  null ; nextToken = input.next(reusableToken)) {          if  (!stopWords.contains(nextToken.termBuffer(),  0 , nextToken.termLength())) {            if  (enablePositionIncrements) {             nextToken.setPositionIncrement(nextToken.getPositionIncrement() + skippedPositions);           }            return  nextToken;         }         skippedPositions += nextToken.getPositionIncrement();       }        // reached EOS -- return null         return   null ;     }  


在这里是调用input的next(),这个input是在初始化stopFilter时进行的,其实input初始化操作也就是也就是把以参数方式传入的result给input,这个result是流经上层的过滤器过来的,回过来看看吧

Java代码  

StandardTokenizer tokenStream =  new  StandardTokenizer(reader, replaceInvalidAcronym);       tokenStream.setMaxTokenLength(maxTokenLength);       TokenStream result =  new  StandardFilter(tokenStream);       result =  new  LowerCaseFilter(result);       result =  new  StopFilter(result, stopSet);  


是LowerCaseFilter, 其实在LowerCaseFilter中,也是按照同样的道理,这样由底层往上层追溯,然后再向下层流,这也是lucene的架构经典之处。

还有在分词器这里,使用的是JAVACC生成的分词器,他的优越性在于简单性和可扩展性。   

作者: Leo_wl

    

出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于lucene 的分析器(analyzer)与分词器(tokenizer)和过滤器(tokenfilt的详细内容...

  阅读:45次

上一篇: java编程陷阱

下一篇:Java面向对象(上)