传送门地址
https://github.com/medcl/elasticsearch-analysis-ik.git
找到与ElasticSearch相对于的版本,然后下载源码(最新源码往往无法编译通过)。
安装忽略
重点说一下业务场景。
由于ik自带分词器往往无法贴合自己公司业务,所以需要增加一个热更新词库管理。
1:配置ik配置文件,找到ik插件的 /config/IKAnalyzer.cfg.xml
修改:
<entry key="remote_ext_dict">http://localhost/hot.words</entry>
配置完成之后需要重启es。ik分词器间隔1分钟(源码可修改间隔)会调用此接口,拉取最新分词,如果Last-Modified或ETag发生变化才会将分词生效。
一般Last-Modified 可以给一个最后修改时间的时间戳
ETag是为了高并发,毫秒级别状态下频繁变更,一般使用所有分词的摘要,例如MD5。
还可以修改源码连接数据库实现分词读取
2:编写springboot接口,此接口从数据库读取维护的分词,并以字符串形式返回。
逻辑代码
public String hotWords() {
HttpServletResponse response = ServletUtils.getResponse();
EsHotWords esHotWords = esHotWordsMapper.selectOne(Wrappers.<EsHotWords>query().select("max(create_time) as create_time", "max(update_time) as update_time"));
LocalDateTime lastTime = esHotWords.getCreateTime().isAfter(esHotWords.getUpdateTime()) ? esHotWords.getCreateTime() : esHotWords.getUpdateTime();
response.setHeader("Last-Modified", String.valueOf(lastTime.toEpochSecond(ZoneOffset.of("+8"))));
response.setHeader("ETag", "app");
List<EsHotWords> hot_words = esHotWordsMapper.selectList(Wrappers.<EsHotWords>query().select("hot_words"));
if (ObjectUtils.isEmpty(hot_words))
return "中文分词\r\n狗东猫宝";
else
return hot_words.stream().map(h -> h.getHotWords()).collect(Collectors.joining("\r\n"));
}
contorller层,调用逻辑层的hotWords方法
@ApiOperation("es分词词库")
@GetMapping("hot.words")
public String hotWords()
{
return xxxService.hotWords();
}
3:由于新增分词,只针对es中新增或发生修改的文档有效。无法针对历史没有发送变更的文档起作用。
所以还要增加一个定期批量更新文档的方法。
/**
* es每天更新一次索引
*/
public void esUpdateByQuery() {
EsHotWords esHotWords = esHotWordsMapper.selectOne(Wrappers.<EsHotWords>query().select("max(create_time) as create_time", "max(update_time) as update_time"));
LocalDateTime lastTime = esHotWords.getCreateTime().isAfter(esHotWords.getUpdateTime()) ? esHotWords.getCreateTime() : esHotWords.getUpdateTime();
String key = "index_esUpdateByQuery";
String value = String.valueOf(lastTime.toEpochSecond(ZoneOffset.of("+8")));
Object obj = redisService.getCacheObject(key);
if (obj != null && obj.toString().equals(value)) {
return;
}
redisService.setCacheObject(key, value);
String url = "http://你的es地址/你的索引名称/_update_by_query?conflicts=proceed";
String post = HttpClientUtil.post(url, null);
logger.info("esUpdateByQuery:\n" + post);
}