分享

一步一步跟我学习lucene(3)---lucene的analysis相关和自定义分词器

 Bladexu的文库 2018-01-10

analysis说明

lucene ananlysis应用场景

lucene提供了analysis用来将文本转换到索引文件或提供给IndexSearcher查询索引;

对于lucene而言,不管是索引还是检索,都是针对于纯文本输入来讲的;

通过lucene的强大类库我们可以访问各种格式的文档,如HTML、XML、PDF、Word、TXT等,

我们需要传递给lucene的只是文件中的纯文本内容;

 lucene的词语切分

lucene的索引和检索前提是其对文本内容的分析和词组的切分;比如,文档中有一句话叫“Hello World,Welcome to China”

我们想找到包含这段话的文档,而用户输入的查询条件又不尽详细(可能只是hello)

这里我们就需要用到lucene索引该文档的时候预先对文档内容进行切分,将词源和文本对应起来。

有时候对词语进行简单切分还远远不够,我们还需要对字符串进行深度切分,lucene不仅能够对索引内容预处理还可以对请求参数进行切分;

使用analyzer

lucene的索引使用如下:

[java] view plain copy
  1. package com.lucene.analysis;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.StringReader;  
  5.   
  6. import org.apache.lucene.analysis.Analyzer;  
  7. import org.apache.lucene.analysis.TokenStream;  
  8. import org.apache.lucene.analysis.standard.StandardAnalyzer;  
  9. import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;  
  10. import org.junit.Test;  
  11.   
  12. public class AnalysisTest {  
  13.     @Test  
  14.     public void tokenTest() {  
  15.         Analyzer analyzer = new StandardAnalyzer(); // or any other analyzer  
  16.         TokenStream ts = null;  
  17.         try {  
  18.             ts = analyzer.tokenStream("myfield"new StringReader(  
  19.                     "some text goes here"));  
  20.             OffsetAttribute offsetAtt = ts.addAttribute(OffsetAttribute.class);  
  21.             ts.reset(); // Resets this stream to the beginning. (Required)  
  22.             while (ts.incrementToken()) {  
  23.                 // Use AttributeSource.reflectAsString(boolean)  
  24.                 // for token stream debugging.  
  25.                 System.out.println("token: " + ts.reflectAsString(true));  
  26.   
  27.                 System.out.println("token start offset: "  
  28.                         + offsetAtt.startOffset());  
  29.                 System.out.println("token end offset: "  
  30.                         + offsetAtt.endOffset());  
  31.             }  
  32.             ts.end();   
  33.         } catch (IOException e) {  
  34.             // TODO Auto-generated catch block  
  35.             e.printStackTrace();  
  36.         } finally {  
  37.             try {  
  38.                 ts.close();  
  39.             } catch (IOException e) {  
  40.                 // TODO Auto-generated catch block  
  41.                 e.printStackTrace();  
  42.             }  
  43.         }  
  44.     }  
  45.   
  46. }  


自定义Analyzer和实现自己的analysis模块

1.要实现自己的analyzer,我们需要继承Analyzer并重写其中的分词模块。

2.维护停止词词典

3.重写TokenStreamComponents方法,选择合适的分词方法,对词语进行过滤

示例代码如下

[java] view plain copy
  1. package com.lucene.analysis.self;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.analysis.Analyzer;  
  6. import org.apache.lucene.analysis.TokenStream;  
  7. import org.apache.lucene.analysis.Tokenizer;  
  8. import org.apache.lucene.analysis.core.LowerCaseTokenizer;  
  9. import org.apache.lucene.analysis.core.StopAnalyzer;  
  10. import org.apache.lucene.analysis.core.StopFilter;  
  11. import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;  
  12. import org.apache.lucene.analysis.util.CharArraySet;  
  13.   
  14. public class MyAnalyzer extends Analyzer {  
  15.     private CharArraySet stopWordSet;//停止词词典  
  16.       
  17.     public CharArraySet getStopWordSet() {  
  18.         return stopWordSet;  
  19.     }  
  20.   
  21.     public void setStopWordSet(CharArraySet stopWordSet) {  
  22.         this.stopWordSet = stopWordSet;  
  23.     }  
  24.   
  25.       
  26.     public MyAnalyzer() {  
  27.         super();  
  28.         this.stopWordSet = StopAnalyzer.ENGLISH_STOP_WORDS_SET;//可在此基础上拓展停止词  
  29.     }  
  30.       
  31.     /**扩展停止词 
  32.      * @param stops 
  33.      */  
  34.     public MyAnalyzer(String[] stops) {  
  35.         this();  
  36.         stopWordSet.addAll(StopFilter.makeStopSet(stops));  
  37.     }  
  38.   
  39.     @Override  
  40.     protected TokenStreamComponents createComponents(String fieldName) {  
  41.         //正则匹配分词  
  42.         Tokenizer source = new LowerCaseTokenizer();  
  43.         return new TokenStreamComponents(source, new StopFilter(source, stopWordSet));  
  44.     }  
  45.     public static void main(String[] args) {  
  46.         Analyzer analyzer = new MyAnalyzer();  
  47.         String words = "A AN yuyu";  
  48.         TokenStream stream = null;  
  49.           
  50.         try {  
  51.             stream = analyzer.tokenStream("myfield", words);  
  52.             stream.reset();   
  53.             CharTermAttribute  offsetAtt = stream.addAttribute(CharTermAttribute.class);  
  54.             while (stream.incrementToken()) {  
  55.                 System.out.println(offsetAtt.toString());  
  56.             }  
  57.             stream.end();  
  58.         } catch (IOException e) {  
  59.             // TODO Auto-generated catch block  
  60.             e.printStackTrace();  
  61.         }finally{  
  62.             try {  
  63.                 stream.close();  
  64.             } catch (IOException e) {  
  65.                 // TODO Auto-generated catch block  
  66.                 e.printStackTrace();  
  67.             }  
  68.         }  
  69.     }  
  70. }  


运行结果如下:

[html] view plain copy
  1. yuyu  

说明该分词器对a an 进行了过滤,这些过滤的词在stopWordSet中

 添加字长过滤器

有时候我们需要对字符串中的短字符进行过滤,比如welcome to BeiJIng中过滤掉长度小于2的字符串,我们期望的结果就变成了Welcome BeiJing,我们仅需要重新实现createComponents方法,相关代码如下:

[java] view plain copy
  1. package com.lucene.analysis.self;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.analysis.Analyzer;  
  6. import org.apache.lucene.analysis.TokenStream;  
  7. import org.apache.lucene.analysis.Tokenizer;  
  8. import org.apache.lucene.analysis.core.LowerCaseTokenizer;  
  9. import org.apache.lucene.analysis.core.StopAnalyzer;  
  10. import org.apache.lucene.analysis.core.StopFilter;  
  11. import org.apache.lucene.analysis.core.WhitespaceTokenizer;  
  12. import org.apache.lucene.analysis.miscellaneous.LengthFilter;  
  13. import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;  
  14. import org.apache.lucene.analysis.util.CharArraySet;  
  15.   
  16. public class LengFilterAanlyzer extends Analyzer {  
  17.     private int len;  
  18.       
  19.     public int getLen() {  
  20.         return len;  
  21.     }  
  22.   
  23.   
  24.     public void setLen(int len) {  
  25.         this.len = len;  
  26.     }  
  27.   
  28.   
  29.     public LengFilterAanlyzer() {  
  30.         super();  
  31.     }  
  32.       
  33.   
  34.     public LengFilterAanlyzer(int len) {  
  35.         super();  
  36.         this.len = len;  
  37.     }  
  38.   
  39.   
  40.     @Override  
  41.     protected TokenStreamComponents createComponents(String fieldName) {  
  42.         final Tokenizer source = new WhitespaceTokenizer();  
  43.         TokenStream result = new LengthFilter(source, len, Integer.MAX_VALUE);  
  44.         return new TokenStreamComponents(source,result);  
  45.   
  46.     }  
  47.     public static void main(String[] args) {  
  48.         Analyzer analyzer = new LengFilterAanlyzer(2);  
  49.         String words = "I am a java coder";  
  50.         TokenStream stream = null;  
  51.           
  52.         try {  
  53.             stream = analyzer.tokenStream("myfield", words);  
  54.             stream.reset();   
  55.             CharTermAttribute  offsetAtt = stream.addAttribute(CharTermAttribute.class);  
  56.             while (stream.incrementToken()) {  
  57.                 System.out.println(offsetAtt.toString());  
  58.             }  
  59.             stream.end();  
  60.         } catch (IOException e) {  
  61.             // TODO Auto-generated catch block  
  62.             e.printStackTrace();  
  63.         }finally{  
  64.             try {  
  65.                 stream.close();  
  66.             } catch (IOException e) {  
  67.                 // TODO Auto-generated catch block  
  68.                 e.printStackTrace();  
  69.             }  
  70.         }  
  71.     }  
  72. }  

程序的执行结果如下:

[html] view plain copy
  1. am  
  2. java  
  3. coder  

说明小于2个字符的文本被过滤了。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多