11
回答
IKanalyzer扩展词库动态加载问题
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   
扩展词库更新后,只有重启搜索服务,重建索引才有效果,如何做到不需要重启搜索服务就能重新加载 扩展词库呢?
举报
blue_air
发帖于4年前 11回/3K+阅
共有11个答案 最后回答: 5个月前

1. 扩展词库更新后, 需要重建索引才能让新词库对已有的数据生效这个是必须的.

2. 新加入词库后, 重启搜索服务这个可以避免. 不知道IK是否支持词库更新自动加载? 不支持的话, 哥们可以试下jcseg.

--- 共有 1 条评论 ---
blue_air没接触过jcseg分词,回头先放到项目中看看效果如何。谢谢!81 4年前 回复

引用来自“狮子的魂”的答案

1. 扩展词库更新后, 需要重建索引才能让新词库对已有的数据生效这个是必须的.

2. 新加入词库后, 重启搜索服务这个可以避免. 不知道IK是否支持词库更新自动加载? 不支持的话, 哥们可以试下jcseg.

你好,我按照jcseg所给的开发文档,安装solr分词用法进行配置,但是启动老报错,是我没有配成功还是?很焦急。。。
org.apache.solr.common.SolrException: Plugin init failure for [schema.xml] fieldType "text_jcset_c": Plugin init failure for [schema.xml] analyzer/tokenizer: Error instantiating class: 'com.webssky.jcseg.solr.JcsegTokenizerFactory'
at org.apache.solr.util.plugin.AbstractPluginLoader.load(AbstractPluginLoader.java:177)
at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:369)
at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:113)
at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1000)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1033)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)

引用来自“blue_air”的答案

引用来自“狮子的魂”的答案

1. 扩展词库更新后, 需要重建索引才能让新词库对已有的数据生效这个是必须的.

2. 新加入词库后, 重启搜索服务这个可以避免. 不知道IK是否支持词库更新自动加载? 不支持的话, 哥们可以试下jcseg.

你好,我按照jcseg所给的开发文档,安装solr分词用法进行配置,但是启动老报错,是我没有配成功还是?很焦急。。。
org.apache.solr.common.SolrException: Plugin init failure for [schema.xml] fieldType "text_jcset_c": Plugin init failure for [schema.xml] analyzer/tokenizer: Error instantiating class: 'com.webssky.jcseg.solr.JcsegTokenizerFactory'
at org.apache.solr.util.plugin.AbstractPluginLoader.load(AbstractPluginLoader.java:177)
at org.apache.solr.schema.IndexSchema.readSchema(IndexSchema.java:369)
at org.apache.solr.schema.IndexSchema.<init>(IndexSchema.java:113)
at org.apache.solr.core.CoreContainer.createFromLocal(CoreContainer.java:1000)
at org.apache.solr.core.CoreContainer.create(CoreContainer.java:1033)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:629)
at org.apache.solr.core.CoreContainer$3.call(CoreContainer.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:441)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
at java.lang.Thread.run(Thread.java:619)

http://www.cnblogs.com/liang1101/articles/6395016.html,这个更详细

不过我改了

    if (!inputStreamList.isEmpty()){
        DictionaryUtil.reloadDic(inputStreamList);
    }
    String lastupdate = p.getProperty("lastupdate", "0");
    String auto = p.getProperty("auto", "0");
    //System.err.println(String.format("read %s file get lastupdate is %s.", this.conf, lastupdate));
    Long t = new Long(lastupdate);
    if("1".equals(auto)){
        this.lastUpdateTime=t-1;
    }
 

        if ( DictionaryUtil.singleton == null) {
            
            DefaultConfig.getInstance();
            Configuration cfg = DefaultConfig.getInstance();
            Dictionary.initial(cfg);
            DictionaryUtil.singleton =  Dictionary.getSingleton();
            return null;
        }else{
            //直接从索引读取一个字段的内容
            SolrUtil.add(singleton);
        }

package org.apache.lucene.analysis.core;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.util.ResourceLoader;
import org.apache.lucene.analysis.util.ResourceLoaderAware;
import org.apache.lucene.analysis.util.TokenizerFactory;//lucene:4.8之前的版本
//import org.apache.lucene.util.AttributeSource.AttributeFactory;
//lucene:4.9
import org.apache.lucene.util.AttributeSource.AttributeFactory;
import org.wltea.analyzer.dic.Dictionary;
import org.wltea.analyzer.lucene.IKTokenizer;

/**
 * @author liangyongxing
 * @editTime 2017-02-06
 * 增加IK扩展词库动态更新类
 */
public class IKTokenizerFactory extends TokenizerFactory
    implements ResourceLoaderAware, UpdateKeeper.UpdateJob {
  private boolean useSmart = false;
  private ResourceLoader loader;
  private long lastUpdateTime = -1L;
  private String conf = null;

  public IKTokenizerFactory(Map<String, String> args) {
    super(args);
    this.useSmart = getBoolean(args, "useSmart", false);
    this.conf = get(args, "conf");
    System.out.println(String.format(":::ik:construction:::::::::::::::::::::::::: %s", this.conf));
  }


    /**
     * 检查是否要更新
     * @return
     */
    private Properties canUpdate() {
        try {
            if (this.conf == null)
                return null;
            Properties p = new Properties();
            InputStream confStream = this.loader.openResource(this.conf);
            p.load(confStream);
            confStream.close();
            String lastupdate = p.getProperty("lastupdate", "0");
            //System.err.println(String.format("read %s file get lastupdate is %s.", this.conf, lastupdate));
            Long t = new Long(lastupdate);
            if (t.longValue() > this.lastUpdateTime) {
                this.lastUpdateTime = t.longValue();
                String paths = p.getProperty("files");
                if ((paths == null) || (paths.trim().isEmpty()))
                    return null;
                System.out.println("loading conf files success.");
                return p;
            }
           
            this.lastUpdateTime = t.longValue();
            return null;
        }
        catch (Exception e) {
            //e.printStackTrace();
            System.err.println("IK parsing conf NullPointerException~~~~~" + e.getStackTrace());
        }
        return null;
    }

    public static List<String> SplitFileNames(String fileNames) {
        if (fileNames == null) {
            return Collections.emptyList();
        }
        List result = new ArrayList();
        for (String file : fileNames.split("[,\\s]+")) {
            result.add(file);
        }
        return result;
    }

  private boolean useSmart() {
    return this.useSmart;
  }


@Override
public Tokenizer create(AttributeFactory attributeFactory, Reader arg1) {
  return new IKTokenizer(arg1, useSmart());
}
//

public void inform(ResourceLoader resourceLoader) throws IOException {
System.out.println(String.format(":::ik:::inform:::::::::::::::::::::::: %s", this.conf));
this.loader = resourceLoader;
update();
if ((this.conf != null) && (!this.conf.trim().isEmpty())) {
    UpdateKeeper.getInstance().register(this);
}
}

public void update() throws IOException {
Properties p = canUpdate();
if (p != null) {
    List<String> dicPaths = SplitFileNames(p.getProperty("files"));
    List inputStreamList = new ArrayList();
    for (String path : dicPaths) {
        if ((path != null) && (!path.isEmpty())) {
            InputStream is = this.loader.openResource(path);

            if (is != null) {
                inputStreamList.add(is);
            }
        }
    }
    if (!inputStreamList.isEmpty()){
        DictionaryUtil.reloadDic(inputStreamList);
    }
    String lastupdate = p.getProperty("lastupdate", "0");
    String auto = p.getProperty("auto", "0");
    //System.err.println(String.format("read %s file get lastupdate is %s.", this.conf, lastupdate));
    Long t = new Long(lastupdate);
    if("1".equals(auto)){
        this.lastUpdateTime=t-1;
    }

}
}

}
 

package org.apache.lucene.analysis.core;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.cfg.DefaultConfig;
import org.wltea.analyzer.dic.Dictionary;

public class DictionaryUtil {
    /**
     * 重新更新词典
     * 由于停用词等不经常变也不建议常增加,故这里只修改动态扩展词库
     * @param inputStreamList
     * @author liangyongxing
     * @createTime 2017年2月7日
     * @return
     */
    public static Dictionary  singleton =null;
    
    public static Dictionary reloadDic(List<InputStream> inputStreamList) {
        //Dictionary singleton =  Dictionary.getSingleton();
        if ( DictionaryUtil.singleton == null) {
            
            DefaultConfig.getInstance();
            Configuration cfg = DefaultConfig.getInstance();
            Dictionary.initial(cfg);
            DictionaryUtil.singleton =  Dictionary.getSingleton();
            return null;
        }else{
            //直接从索引读取一个字段的内容
            SolrUtil.add(singleton);
        }
        for (InputStream is : inputStreamList) {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 512);
                String theWord = null;
                HashMap<String, String> map = new HashMap();
                List<String> words  = new ArrayList<String>();
                do {
                    theWord = br.readLine();
                    if (theWord != null && !"".equals(theWord.trim())) {
                        words.add(theWord);
                        //singleton._MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
                    }
                } while (theWord != null);
                singleton.addWords(words);
            } catch (IOException ioe) {
                System.err.println("Other Dictionary loading exception.");
                ioe.printStackTrace();
            } finally {
                try {
                    if (is != null) {
                        is.close();
                        is = null;
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
         
        }
        

        return singleton;
    }
}
 

顶部