-
在 github.com/medcl/elast… 下载源码,然后解压后倒入 idea ,等待下载相关包,可能需要耗时若干分钟。可能在 pom.xml 文件中有爆红,不用管,不影响编译即可。
-
在 org.wltea.analyzer.dic.Dictionary 中的 initial 方法直接用以下代码覆盖
public static synchronized Dictionary 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(); pool.scheduleAtFixedRate(new MysqlHotWordMonitor(), 10, 60, TimeUnit.SECONDS); 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); } } return singleton; } } } return singleton; } -
同目录下创建 MysqlHotWordMonitor 类,直接复制以下代码,这里连接的是 postgres 数据库,我提前在库里创建了一张 tokens 表,里面有一个 key 字段用来保存分词,代码会将该表中的分词都加载到一个 strings 列表中并返回,应该很好理解。同理这里代码可以改用 mysql 等其他数据库。
public class MysqlHotWordMonitor implements Runnable{
private static final Logger logger = ESPluginLoggerFactory.getLogger(Monitor.class.getName()); private static final String DATABASE_CONF = "database_conf.txt"; public static Map loadConf(){ Map map = new HashMap<String,String>(); Path file = PathUtils.get(org.wltea.analyzer.dic.Dictionary.getSingleton().conf_dir.toAbsolutePath().toString(), DATABASE_CONF); try (InputStream is = new FileInputStream(file.toFile())) { BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"), 512); String line = br.readLine(); while (line!= null && !line.equals("")) { String [] words = line.split(": "); map.put(words[0], words[1]); line = br.readLine(); } } catch (FileNotFoundException e) { logger.error("ik-analyzer: not found", e); } catch (IOException e) { logger.error("ik-analyzer: loading failed", e); } return map; } static List<String> loadMysqlDict(){ Statement statement; Connection conn; List<String> strings = new ArrayList<>(); Map<String,String> map = loadConf(); try { Class.forName("org.postgresql.Driver"); System.out.println("准备!"); conn = DriverManager.getConnection(String.format("jdbc:postgresql://%s:%s/%s", map.get("host"), map.get("port"), map.get("database")), map.get("user"), map.get("password")); System.out.println("连接 " + map.get("host") + " 服务器中的 " +map.get("database") +" 数据库成功!"); String sql = "select distinct(key) FROM "+map.get("tableName"); statement = conn.createStatement(); ResultSet rs = statement.executeQuery(sql); System.out.println("加载 "+map.get("tableName")+" 表中分词"); while (rs.next()){ String word = rs.getString("key"); if (word != null && !"".equals(word.trim())) { // 加载扩展词典数据到主内存词典中 strings.add(word); } } }catch (Exception e){ e.printStackTrace(); System.out.println("loadMysqlDict 异常"); } return strings; } @Override public void run() { Statement statement = null; Connection conn = null; try { Dictionary.getSingleton().reLoadMainDict(); } catch (Exception e) { e.printStackTrace(); System.out.println("run 异常"); }finally { try { if(statement!=null&&!statement.isClosed()){ statement.close(); } if(conn!=null&&!conn.isClosed()){ conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } }} 4.返回 Dictionary 中,找到 loadMainDict 方法,改为如下代码
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(); // 修改添加加载mysql词库 this.loadMysqlDict(); } -
创建一个新的方法 loadMysqlDict ,代码如下
private void loadMysqlDict() { try { List<String> words = MysqlHotWordMonitor.loadMysqlDict(); for (String word : words){ _MainDict.fillSegment(word.trim().toLowerCase().toCharArray()); } }catch (Exception e){ e.printStackTrace(); System.out.println("loadMysqlDict 异常"); } } -
在 pom.xml 中加入依赖,用到什么数据库就加什么依赖,我这里是 postgres
<dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>42.2.14</version> </dependency> -
将 plugin.xml 中的
<includes> <include>org.apache.httpcomponents:httpclient</include> </includes>改为
<includes> <include>org.apache.httpcomponents:httpclient</include> <include>org.postgresql:postgresql</include> </includes> -
在 config 下面创建一个文件 database_conf.txt ,内容如下,表示要进行读取的数据库信息。
host: 数据库 ip port: 数据库 端口 user: 账号 password: 密码 database: 数据库名 tableName: 表名 -
进行 maven package
-
将 releases 目录下面新生成的 的 zip 包解压后生成的文件夹改名为 ik ,放入 /elasticsearch主目录/plugins 下
-
将 ik 目录下面的 plugin-descriptor.properties 中最后的 elasticsearch.version 改为自己所使用的 elasticsearch 版本号,要完全一致
-
(此步骤可选)如果爆 java.security.AccessControlException: access denied ,可以使用该方法进行解决,在 elasticsearch 主目录/jdk/lib/security/default.policy 中的 grant 中加入如下代码
// 连接数据库 permission java.net.SocketPermission "*", "connect,resolve";
如果不能,则有可能系统使用的是其他路径的 java ,去 %JAVA_HOME%/jre/lib/security/java.policy 中进行相同的操作,重启 es ,如果能够显示代码中需要打印的信息,表示可以正常读取。