Lucene使用IKAnalyzer动态扩展词库

Luncene版本3.6.0 IKAnalyzer 版本2012_u6

最近在使用Luncene+IKAnalyzer做全文检索遇到了IKAnalyzer分词不能满足要求。通过查找资源发现有很多种方式可以扩展字典,下面我来介绍一下这两种方式:

第一种方式:
通过配置文件来扩展字典
在src下面建立IKAnalyzer.cfg.xml
<?
xml version = "1.0" encoding = "UTF-8" ?>
<! DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> 
< properties
     < comment >IK Analyzer 扩展配置</ comment >
     <!-- 用户可以在这里配置自己的扩展字典 -->
      < entry key = "ext_dict" >com/dh/lucene/ext_begin.dic</ entry >
      <!-- 用户可以在这里配置自己的扩展停用词字典    -->
     < entry key = "ext_stopwords" >com/dh/lucene/ext_stopword.dic</ entry >
</ properties >

建立字典文件ext_begin.dicext_stopword.dic 这里需要注意字典文件格式是无BOM 的UTF-8 编码的中文文本文件,可以通过editplus进行修改。

具体Tools->Configure User Tools->File 选择UTF-8无bom格式。

在dic中维护字典即可。

第二种方式:

建立MyConfiguration类,这个类也是在网上搜集到的。

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.InvalidPropertiesFormatException;
import java.util.List;
import java.util.Properties;

/**
 * Configuration 默认实现
 *
 */
public class MyConfiguration implements Configuration{
    //懒汉单例
    private static final Configuration CFG = new MyConfiguration();
    /*
     * 分词器默认字典路径
     */
    private String PATH_DIC_MAIN = "org/wltea/analyzer/dic/main2012.dic";
    private static final String   //    MyConfiguration mycfg = new MyConfiguration();           
    /*
     * 分词器配置文件路径
     */    
    private static final String FILE_NAME = "IKAnalyzer.cfg.xml";
    //配置属性——扩展字典
    private static final String EXT_DICT = "ext_dict";
    //配置属性——扩展停止词典
    private static final String EXT_STOP = "ext_stopwords";
    
    private Properties props;
    /*
     * 是否使用smart方式分词
     */
    private boolean useSmart;
    /**
     * 返回单例
     * @return Configuration单例
     */
    public static Configuration getInstance(){
        return CFG;
    }
    /*
     * 初始化配置文件
     */
     public MyConfiguration(){        
        props = new Properties();
        
        InputStream input = this.getClass().getClassLoader().getResourceAsStream(FILE_NAME);
        if(input != null){
            try {
                props.loadFromXML(input);
            } catch (InvalidPropertiesFormatException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 返回useSmart标志位
     * useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
     * @return useSmart
     */
    public boolean useSmart() {
        return useSmart;
    }
    /**
     * 设置useSmart标志位
     * useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
     * @param useSmart
     */
    public void setUseSmart(boolean useSmart) {
        this.useSmart = useSmart;
    }    
    
    
    /**
    新加函数:设置主词典路径
    * @return String
    主词典路径
    */
    public void setMainDictionary(String path) {
        this.PATH_DIC_MAIN = path;
    }
    
    /**
     * 获取主词典路径
     *
     * @return String 主词典路径
     */
    public String getMainDictionary(){
        return PATH_DIC_MAIN;
    }

    /**
     * 获取量词词典路径
     * @return String 量词词典路径
     */
    public String getQuantifierDicionary(){
        return PATH_DIC_QUANTIFIER;
    }

    /**
     * 获取扩展字典配置路径
     * @return List<String> 相对类加载器的路径
     */
    public List<String> getExtDictionarys(){
        List<String> extDictFiles = new ArrayList<String>(2);
        String extDictCfg = props.getProperty(EXT_DICT);
        if(extDictCfg != null){
            //使用;分割多个扩展字典配置
            String[] filePaths = extDictCfg.split(";");
            if(filePaths != null){
                for(String filePath : filePaths){
                    if(filePath != null && !"".equals(filePath.trim())){
                        extDictFiles.add(filePath.trim());
                    }
                }
            }
        }        
        return extDictFiles;        
    }


    /**
     * 获取扩展停止词典配置路径
     * @return List<String> 相对类加载器的路径
     */
    public List<String> getExtStopWordDictionarys(){
        List<String> extStopWordDictFiles = new ArrayList<String>(2);
        String extStopWordDictCfg = props.getProperty(EXT_STOP);
        if(extStopWordDictCfg != null){
            //使用;分割多个扩展字典配置
            String[] filePaths = extStopWordDictCfg.split(";");
            if(filePaths != null){
                for(String filePath : filePaths){
                    if(filePath != null && !"".equals(filePath.trim())){
                        extStopWordDictFiles.add(filePath.trim());
                    }
                }
            }
        }        
        return extStopWordDictFiles;        
    }           
}

使用方式:

 MyConfiguration mycfg = new MyConfiguration();
 mycfg.setUseSmart(true);
 // 设置为智能分词
 mycfg.setMainDictionary("com/dh/lucene/ext_begin.dic.dic");

Dictionary.initial(mycfg);

  Analyzer mAnalyzer = new IKAnalyzer();   

这样不需要走配置文件方式直接使用自定义字典。


第三种方式为通过使用addWords方法,批量加载新词条,根据业务需求可以在生成索引前把需要的词添加进去:

 Dictionary dg = Dictionary.getSingleton();
 List<String> list=new ArrayList<String>();
 list.add("需要动态添加的词");
 dg.addWords(list);

Analyzer mAnalyzer = new IKAnalyzer();   




建立索引文件

 public static void createIndex(String lupath,Word word){  
            try {  
                File path = new File(lupath+"LuceneEx");  //索引文件存放路径
                Directory mdDirectory = FSDirectory.open(path); 

      //-------------第二种方式------------------
            //    MyConfiguration mycfg = new MyConfiguration();
              //  mycfg.setUseSmart(true);
                // 设置为智能分词
             //   mycfg.setMainDictionary("com/dh/lucene/ext_stopword.dic");
                //动态设置自定义的词库
            //    IKSegmenter seg = new IKSegmenter(new StringReader(text) ,mycfg);
                //Dictionary.initial(mycfg);

     //-------------第二种方式------------------

                Dictionary dg = Dictionary.getSingleton();
                List<String> strList=new ArrayList<String>();
                strList.add(word.getT_model_title());
                dg.addWords(strList);
             // 使用Lucene提供的分词器    
//              Analyzer mAnalyzer = new StandardAnalyzer(Version.LUCENE_36);  
                // 使用 商业分词器     
            /*   
             *  Analyzer analyzer = new IKAnalyzer();//细粒度切分算法
                Analyzer analyzer = new IKAnalyzer(true);//智能切分
                */
                Analyzer mAnalyzer = new IKAnalyzer();    
          
                LogMergePolicy mergePolicy = new LogByteSizeMergePolicy();
                 //设置segment添加文档(Document)时的合并频率
                mergePolicy.setMergeFactor(20);
                //设置segment最大合并文档(Document)数
                mergePolicy.setMaxMergeDocs(500);
                //启用复合式索引文件格式,合并多个segment
                mergePolicy.setUseCompoundFile(true);
              
                IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, mAnalyzer);
             
                config.setMergePolicy(mergePolicy);
                  //设置索引的打开模式
                config.setOpenMode(OpenMode.CREATE_OR_APPEND);
                IndexWriter writer = new IndexWriter(mdDirectory, config);  
                long start = System.currentTimeMillis();  
                    Document doc = new Document();  
                    /**
                       *   Field.Store.YES:存储字段值(未分词前的字段值)
                           Field.Store.NO:不存储,存储与索引没有关系
                           Field.Store.COMPRESS:压缩存储,用于长文本或二进制,但性能受损
                    
                           Field.Index.ANALYZED:分词建索引
                           Field.Index.ANALYZED_NO_NORMS:分词建索引,但是Field的值不像通常那样被保存,而是只取一个byte,这样节约存储空间
                           Field.Index.NOT_ANALYZED:不分词且索引
                           Field.Index.NOT_ANALYZED_NO_NORMS:不分词建索引,Field的值去一个byte保存
                    
                           TermVector表示文档的条目(由一个Document和Field定位)和它们在当前文档中所出现的次数
                           Field.TermVector.YES:为每个文档(Document)存储该字段的TermVector
                           Field.TermVector.NO:不存储TermVector
                           Field.TermVector.WITH_POSITIONS:存储位置
                           Field.TermVector.WITH_OFFSETS:存储偏移量
                           Field.TermVector.WITH_POSITIONS_OFFSETS:存储位置和偏移量
                       */
                


     //----------业务需要---------------     
                    String c = "";
                    JSONArray array = JSONArray.fromObject(word.getT_model_concent());
                    for(int i = 0; i < array.size(); i++){
                         JSONObject jsonObject1 = array.getJSONObject(i);
                         if(jsonObject1.getString("type").equals("basicInfoModule")){
                             if(jsonObject1.getString("text")!=null&&!jsonObject1.getString("text").equals("")&&jsonObject1.getString("text").length()>0){
                             c = jsonObject1.getString("text");
                             }
                          }
                    }        
                    //----------业务需要---------------


                    Field id = new Field("t_modelid", word.getT_modelid(),Store.YES, Index.NOT_ANALYZED);
                    Field title = new Field("title", word.getT_model_title(), Store.YES, Index.NOT_ANALYZED); 
                    Field concent = new Field("concent", c, Store.YES, Index.NOT_ANALYZED);
               
                    doc.add(id); 
                    doc.add(title);  
                    doc.add(concent);

                    writer.addDocument(doc);  
                writer.commit();
                //   writer.forceMerge(1);// 优化
                writer.close();  
                long end = System.currentTimeMillis();  
                System.out.println("createIndex耗时"+(end-start)+"ms");  
                  
            } catch (CorruptIndexException e) {  
                e.printStackTrace();  
            } catch (LockObtainFailedException e) {  
                e.printStackTrace();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        } 






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值