Lucene5学习之自定义同义词分词器简单示例

简介:

  同义词功能在全文搜索时的意义,大家应该都懂的。今天中文我就试着写了一个同义词分词的示例demo,其实主要代码还是参考Lucene in Action 这本英文版书籍的随书代码,只不过Lucenen in Action书里的示例代码目前最新版只支持到Lucene4.x,对于Lucene5.x,代码需要稍作修改,下面是基于Lucene5.x的自定义同义词分词器demo:

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.analyzer.synonym;  
  2.   
  3. import java.io.IOException;  
  4. /** 
  5.  * 同义词提取引擎 
  6.  * @author Lanxiaowei 
  7.  * 
  8.  */  
  9. public interface SynonymEngine {  
  10.     String[] getSynonyms(String s) throws IOException;  
  11. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.analyzer.synonym;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.HashMap;  
  5.   
  6. public class BaseSynonymEngine implements SynonymEngine {  
  7.     private static HashMap<String, String[]> map = new HashMap<String, String[]>();  
  8.       
  9.     {  
  10.         map.put("quick"new String[] {"fast","speedy"});  
  11.         map.put("jumps"new String[] {"leaps","hops"});  
  12.         map.put("over"new String[] {"above"});  
  13.         map.put("lazy"new String[] {"apathetic","slugish"});  
  14.         map.put("dog"new String[] {"canine","pooch"});  
  15.     }  
  16.   
  17.     public String[] getSynonyms(String s) throws IOException {  
  18.         return map.get(s);  
  19.     }  
  20. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.analyzer.synonym;  
  2.   
  3. import java.io.IOException;  
  4. import java.util.Stack;  
  5.   
  6. import org.apache.lucene.analysis.TokenFilter;  
  7. import org.apache.lucene.analysis.TokenStream;  
  8. import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;  
  9. import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;  
  10. import org.apache.lucene.util.AttributeSource;  
  11.   
  12. /** 
  13.  * 自定义同义词过滤器 
  14.  *  
  15.  * @author Lanxiaowei 
  16.  *  
  17.  */  
  18. public class SynonymFilter extends TokenFilter {  
  19.     public static final String TOKEN_TYPE_SYNONYM = "SYNONYM";  
  20.   
  21.     private Stack<String> synonymStack;  
  22.     private SynonymEngine engine;  
  23.     private AttributeSource.State current;  
  24.   
  25.     private final CharTermAttribute termAtt;  
  26.     private final PositionIncrementAttribute posIncrAtt;  
  27.   
  28.     public SynonymFilter(TokenStream in, SynonymEngine engine) {  
  29.         super(in);  
  30.         synonymStack = new Stack<String>(); // #1  
  31.         this.engine = engine;  
  32.   
  33.         this.termAtt = addAttribute(CharTermAttribute.class);  
  34.         this.posIncrAtt = addAttribute(PositionIncrementAttribute.class);  
  35.     }  
  36.   
  37.     public boolean incrementToken() throws IOException {  
  38.         if (synonymStack.size() > 0) { // #2  
  39.             String syn = synonymStack.pop(); // #2  
  40.             restoreState(current); // #2  
  41.             // 这里Lucene4.x的写法  
  42.             // termAtt.setTermBuffer(syn);  
  43.   
  44.             // 这是Lucene5.x的写法  
  45.             termAtt.copyBuffer(syn.toCharArray(), 0, syn.length());  
  46.             posIncrAtt.setPositionIncrement(0); // #3  
  47.             return true;  
  48.         }  
  49.   
  50.         if (!input.incrementToken()) // #4  
  51.             return false;  
  52.   
  53.         if (addAliasesToStack()) { // #5  
  54.             current = captureState(); // #6  
  55.         }  
  56.   
  57.         return true// #7  
  58.     }  
  59.   
  60.     private boolean addAliasesToStack() throws IOException {  
  61.         // 这里Lucene4.x的写法  
  62.         // String[] synonyms = engine.getSynonyms(termAtt.term()); //#8  
  63.   
  64.         // 这里Lucene5.x的写法  
  65.         String[] synonyms = engine.getSynonyms(termAtt.toString()); // #8  
  66.   
  67.         if (synonyms == null) {  
  68.             return false;  
  69.         }  
  70.         for (String synonym : synonyms) { // #9  
  71.             synonymStack.push(synonym);  
  72.         }  
  73.         return true;  
  74.     }  
  75. }  
  76.   
  77. /* 
  78. #1 Define synonym buffer 
  79. #2 Pop buffered synonyms 
  80. #3 Set position increment to 0 
  81. #4 Read next token 
  82. #5 Push synonyms onto stack 
  83. #6 Save current token 
  84. #7 Return current token 
  85. #8 Retrieve synonyms 
  86. #9 Push synonyms onto stack 
  87. */  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.analyzer.synonym;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.Reader;  
  5. import java.io.StringReader;  
  6.   
  7. import org.apache.lucene.analysis.Analyzer;  
  8. import org.apache.lucene.analysis.TokenStream;  
  9. import org.apache.lucene.analysis.Tokenizer;  
  10. import org.apache.lucene.analysis.Analyzer.TokenStreamComponents;  
  11. import org.apache.lucene.analysis.core.LetterTokenizer;  
  12. import org.apache.lucene.analysis.core.LowerCaseFilter;  
  13. import org.apache.lucene.analysis.core.StopAnalyzer;  
  14. import org.apache.lucene.analysis.core.StopFilter;  
  15. import org.apache.lucene.analysis.standard.StandardFilter;  
  16. import org.apache.lucene.analysis.standard.StandardTokenizer;  
  17.   
  18. import com.yida.framework.lucene5.util.analyzer.codec.MetaphoneReplacementFilter;  
  19.   
  20. /** 
  21.  * 自定义同义词分词器 
  22.  *  
  23.  * @author Lanxiaowei 
  24.  * @createTime 2015-03-31 10:15:23 
  25.  */  
  26. public class SynonymAnalyzer extends Analyzer {  
  27.   
  28.     private SynonymEngine engine;  
  29.   
  30.     public SynonymAnalyzer(SynonymEngine engine) {  
  31.         this.engine = engine;  
  32.     }  
  33.   
  34.     @Override  
  35.     protected TokenStreamComponents createComponents(String text) {  
  36.         Tokenizer tokenizer = new StandardTokenizer();  
  37.         TokenStream tokenStream = new SynonymFilter(tokenizer, engine);  
  38.         tokenStream = new LowerCaseFilter(tokenStream);  
  39.         tokenStream = new StopFilter(tokenStream,StopAnalyzer.ENGLISH_STOP_WORDS_SET);  
  40.         return new TokenStreamComponents(tokenizer, tokenStream);  
  41.     }  
  42. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.analyzer.synonym;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import org.apache.lucene.analysis.Analyzer;  
  6.   
  7. import com.yida.framework.lucene5.util.AnalyzerUtils;  
  8.   
  9. public class SynonymAnalyzerTest {  
  10.     public static void main(String[] args) throws IOException {  
  11.         String text = "The quick brown fox jumps over the lazy dog";  
  12.         Analyzer analyzer = new SynonymAnalyzer(new BaseSynonymEngine());  
  13.         AnalyzerUtils.displayTokens(analyzer, text);  
  14.     }  
  15. }  

 

Java代码   收藏代码
  1. package com.yida.framework.lucene5.util;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import junit.framework.Assert;  
  6.   
  7. import org.apache.lucene.analysis.Analyzer;  
  8. import org.apache.lucene.analysis.TokenStream;  
  9. import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;  
  10. import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;  
  11. import org.apache.lucene.analysis.tokenattributes.PositionIncrementAttribute;  
  12. import org.apache.lucene.analysis.tokenattributes.TypeAttribute;  
  13.   
  14. /** 
  15.  * 用于分词器测试的一个简单工具类(用于打印分词情况,包括Term的起始位置和结束位置(即所谓的偏 * 移量),位置增量,Term字符串,Term字符串类型(字符串/阿拉伯数字之类的)) 
  16.  * @author Lanxiaowei 
  17.  * 
  18.  */  
  19. public class AnalyzerUtils {  
  20.     public static void displayTokens(Analyzer analyzer,String text) throws IOException {  
  21.         TokenStream tokenStream = analyzer.tokenStream("text", text);  
  22.         displayTokens(tokenStream);  
  23.     }  
  24.       
  25.     public static void displayTokens(TokenStream tokenStream) throws IOException {  
  26.         OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);  
  27.         PositionIncrementAttribute positionIncrementAttribute = tokenStream.addAttribute(PositionIncrementAttribute.class);  
  28.         CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);  
  29.         TypeAttribute typeAttribute = tokenStream.addAttribute(TypeAttribute.class);  
  30.           
  31.         tokenStream.reset();  
  32.         int position = 0;  
  33.         while (tokenStream.incrementToken()) {  
  34.             int increment = positionIncrementAttribute.getPositionIncrement();  
  35.             if(increment > 0) {  
  36.                 position = position + increment;  
  37.                 System.out.print(position + ":");  
  38.             }  
  39.             int startOffset = offsetAttribute.startOffset();  
  40.             int endOffset = offsetAttribute.endOffset();  
  41.             String term = charTermAttribute.toString();  
  42.             System.out.println("[" + term + "]" + ":(" + startOffset + "-->" + endOffset + "):" + typeAttribute.type());  
  43.         }  
  44.     }  
  45.       
  46.     /** 
  47.      * 断言分词结果 
  48.      * @param analyzer 
  49.      * @param text        源字符串 
  50.      * @param expecteds   期望分词后结果 
  51.      * @throws IOException  
  52.      */  
  53.     public static void assertAnalyzerTo(Analyzer analyzer,String text,String[] expecteds) throws IOException {  
  54.         TokenStream tokenStream = analyzer.tokenStream("text", text);  
  55.         CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);  
  56.         for(String expected : expecteds) {  
  57.             Assert.assertTrue(tokenStream.incrementToken());  
  58.             Assert.assertEquals(expected, charTermAttribute.toString());  
  59.         }  
  60.         Assert.assertFalse(tokenStream.incrementToken());  
  61.         tokenStream.close();  
  62.     }  
  63. }  

 以上代码都是Lucene in Action这本书里面的示例代码,只不过是基于Lucene5.x把它重写并调试成功了,特此分享,希望对正在学习Lucene5的童鞋们有所帮助。demo代码我会在底下附件里上传,有需要demo源码的请自己在底下的附件里下载,Lucene in Action这本书的随书源码我已上传到我的百度网盘,也一并分享给大家,Lucene in Action随书源码百度网盘下载地址

       戳我,戳我,快戳我!!!Come on.

      

      千言万语都在代码中,就不多说了,打完收工!

 

 

如果你还有什么问题请加我Q-Q:7-3-6-0-3-1-3-0-5,

或者加裙
一起交流学习!

转载:http://iamyida.iteye.com/blog/2197355

目录
相关文章
|
29天前
|
JSON 自然语言处理 Java
es索引、类型(mapping)、文档、ik分词器
es索引、类型(mapping)、文档、ik分词器
|
10月前
|
存储 JSON 自然语言处理
三.全文检索ElasticSearch经典入门-索引CRUD&分词器&文档映射&文档CRUD
三.全文检索ElasticSearch经典入门-索引CRUD&分词器&文档映射&文档CRUD
|
12月前
|
自然语言处理 搜索推荐 Python
jieba分词器(应用及字典的补充)及文档高频词提取实战
jieba分词器(应用及字典的补充)及文档高频词提取实战
|
容器
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(六)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(六)
133 0
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(六)
|
JSON 数据格式 索引
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(一)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(一)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(一)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(五)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(五)
|
索引
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(七)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(七)
|
索引
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(四)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(四)
122 0
|
搜索推荐 关系型数据库 索引
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(二)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(二)
101 0
|
索引
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(三)
ElasticSearch03_Mapping字段映射、常用类型、数据迁移、ik分词器、自定义分词器(三)
106 0

热门文章

最新文章