ES 中文分词器ik及自定义远程词库

ik分词器安装部署 

下载地址:https://github.com/medcl/elasticsearch-analysis-ik

注意es和ik分词器的版本匹配.这里下载7.9.3的ik分词器

下载完毕之后去es的工作目录的plugins文件夹下新建ik文件夹,将下载下来的ik压缩包解压缩至ik文件夹下,重启e

 

 

 

词库介绍

ik分词器主要有以下词库,位于config目录下

(1)、main.dic 主词库,包含日常生活中常用的词

(2)、stopword.dic 英文停用词,当出现该词库中的文本内容时,将不会建立倒排索引

(3)、quantifier.dic 计量单位等

(4)、suffix.dic 后缀名、行政单位等

(5)、surname.dic 百家姓等

(6)、preposition.dic 语气词等

 

IK中文分词器插件给我们提供了两个分析器

ik_max_word : 会将文本做最细粒度的拆分
ik_smart:会做最粗粒度的拆分

 

创建索引时指定IK分词器 

PUT ik_index
{
    "mappings": {
        "properties": {
            "id": {
                "type": "long"
            },
            "title": {
                "type": "text",
                "analyzer": "ik_max_word"
            }
        }
    }
}

 

为索引指定默认IK分词器

PUT ik_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "ik_max_word"
        }
      }
    }
  }
}

 

 

自定义热词配置介绍

热词配置方式

(1)、自定义文件

(2)、自定义接口

(3)、基于远程数据库

 

基于自定义文件

IKAnalyzer.cfg.xml ik配置文件位于config目录下,可在此文件配置自定义热词、停词

 

手动配置

一般情况下,词库是够用的,但是如果碰到一些特殊词汇如网络用词,这个时候就需要手动添加相关的词汇进入到词库中.ik添加自定义词库的步骤如下

(1)、在config目录下,新增自定义词库文件

 

 

 (2)、将新增的文件配置的到IKAnalyzer.cfg.xml

 (3)、效果测试

 

基于自定义接口

自定义接口方式类似于自定义文件方式

 

 

基于数据库方式

(1)、gitHub拉去es对应版本的ik分词代码

(2)、打开项目并增加连接代码

(3)、ik分词项目打包

(4)、上jar文件到指定位置

 

gitHub拉去es对应版本的ik分词代码

ik分词地址:https://github.com/medcl/elasticsearch-analysis-ik/releases?page=7

 

打开项目并增加连接代码

1.在项目config文件下新增jdbc-reload.properties文件

jdbc.url=jdbc:mysql://192.168.225.1:3306/my_ik?serverTimeZone=UFT&useSSL=false
jdbc.user=root
jdbc.password=123456
# 更新词库
jdbc.reload.sql=select word from es_ik_extensions_word
# 更新停用词词库
jdbc.reload.stopword.sql=select word from es_ik_stop_word
jdbc.reload.interval=1000

 

2.新增一个线程类HotDicReloadThread用于循环调用,在词典管理类Dictionary文件下找到loadMainDict(加载主词典及扩展词典)并新增方法loadMySqlExtDict,然后将HotDicReloadThread天加到init方法

public class HotDicReloadThread implements Runnable{
    private static final org.apache.logging.log4j.Logger logger = ESPluginLoggerFactory.getLogger(Dictionary.class.getName());
    @Override
    public void run() {
        while (true){
            logger.info("-------重新加载mysql词典--------");
            Dictionary.getSingleton().reLoadMainDict();
        }
    }
}
    /**
     * 加载主词典及扩展词典
     */
    private void loadMainDict() {
        // 建立一个主词典实例
        _MainDict = new DictSegment((char) 0);

        // 读取主词典文件
        Path file = PathUtils.get(getDictRoot(), Dictionary.PATH_DIC_MAIN);
        loadDictFile(_MainDict, file, false, "Main Dict");
        // 加载扩展词典
        this.loadExtDict();
        // 加载远程自定义词库
        this.loadRemoteExtDict();
        // 加载远程数据库自定义词库
        this.loadMySqlExtDict();
    }
    /**
     * 加载远程数据库词典到主词库表
     */
    private void loadMySqlExtDict() {
        Connection connection = null;
        Statement statement = null;
        ResultSet resultSet = null;

        try {
            Path file = PathUtils.get(getDictRoot(), "jdbc-reload.properties");
            prop.load(new FileInputStream(file.toFile()));

            logger.info("-------jdbc-reload.properties-------");
            for (Object key : prop.keySet()) {
                logger.info("key:{}", prop.getProperty(String.valueOf(key)));
            }

            logger.info("------- 查询词典, sql:{}-------", prop.getProperty("jdbc.reload.sql"));

            // 建立mysql连接
            connection = DriverManager.getConnection(
                    prop.getProperty("jdbc.url"),
                    prop.getProperty("jdbc.user"),
                    prop.getProperty("jdbc.password")
            );

            // 执行查询
            statement = connection.createStatement();
            resultSet = statement.executeQuery(prop.getProperty("jdbc.reload.sql"));

            // 循环输出查询啊结果,添加到Main.dict中去
            while (resultSet.next()) {
                String theWord = resultSet.getString("word");
                if (theWord != null && !"".equals(theWord.trim())) {
                    logger.info("------热更新词典:{}------", theWord);
                    // 加到mainDict里面
                    _MainDict.fillSegment(theWord.trim().toCharArray());
                }
            }
            Thread.sleep(Integer.valueOf(String.valueOf(prop.get("jdbc.reload.interval"))));

        } catch (Exception e) {
            logger.error("error:{}", e);
        } finally {
            try {
                if (resultSet != null) {
                    resultSet.close();
                }
                if (statement != null) {
                    statement.close();
                }
                if (connection != null) {
                    connection.close();
                }
            } catch (SQLException e) {
                logger.error("error", e);
            }
        }
    }

 

    /**
     * 词典初始化 由于IK Analyzer的词典采用Dictionary类的静态方法进行词典初始化
     * 只有当Dictionary类被实际调用时,才会开始载入词典, 这将延长首次分词操作的时间 该方法提供了一个在应用加载阶段就初始化字典的手段
     * 
     * @return Dictionary
     */
    public static synchronized void initial(Configuration cfg) {
        if (singleton == null) {
            synchronized (Dictionary.class) {
                if (singleton == null) {

                    singleton = new Dictionary(cfg);
                    singleton.loadMainDict();
                    singleton.loadSurnameDict();
                    singleton.loadQuantifierDict();
                    singleton.loadSuffixDict();
                    singleton.loadPrepDict();
                    singleton.loadStopWordDict();
                    // 执行更新mysql词库的线程
                    new Thread(new HotDicReloadThread()).start();
                    
                    if(cfg.isEnableRemoteDict()){
                        // 建立监控线程
                        for (String location : singleton.getRemoteExtDictionarys()) {
                            // 10 秒是初始延迟可以修改的 60是间隔时间 单位秒
                            pool.scheduleAtFixedRate(new Monitor(location), 10, 60, TimeUnit.SECONDS);
                        }
                        for (String location : singleton.getRemoteExtStopWordDictionarys()) {
                            pool.scheduleAtFixedRate(new Monitor(location), 10, 60, TimeUnit.SECONDS);
                        }
                    }

                }
            }
        }
    }

 

3.配置自定义的数据库热词

在/opt/es/elasticsearch-7.9.3/plugins/ik/config新增jdbc-reload.properties并新增内容同项目的jdbc-reload.properties

jdbc.url=jdbc:mysql://192.168.225.1:3306/my_ik?serverTimeZone=UFT8&useSSL=false
jdbc.user=root
jdbc.password=123456
# 更新词库
jdbc.reload.sql=select word from es_ik_extensions_word
# 更新停用词词库
jdbc.reload.stopword.sql=select word from es_ik_stop_word
jdbc.reload.interval=1000

 

将打包后的elasticsearch-analysis-ik-7.9.3.jar放入目录下

 

重启es可以看到读取到数据的内容

 

 

效果测试

 

posted @ 2023-07-02 16:36  爵士灬  阅读(1739)  评论(0编辑  收藏  举报