(1)elasticsearch集群,且都装有ik分词器
ik分词器安装参看下:https://blog.csdn.net/chen_2890/article/details/83757022
(2)安装有nginx作为静态资源服务器(使用这种方式需依赖nginx通过http访问,依赖于网络和nginx的稳定,可以采用修改Ik分词器原来,通过从mysql中获取分词数据)
ik分词器源码地址:https://github.com/medcl/elasticsearch-analysis-ik/tree/v5.2.0
1.获取ik中配置文件 IKAnalyzer.cfg.xml Properties props加载配置文件值
2. 开启远程词典时,查找配置的远程词典文件路径,从prop属性中查找出remote_ext_dict 配置项的值,处理成文件路径列表
3.每个远程词典文件开启一个监控线程,进行监控,每60秒调度一次,运行Monitor 里的run方法
4.run方法里访问远程词典,保存上一次的Last-Modified 根据响应的上次修改时间与保存的上次修改时间判断远程文件是否变化,变化的话重新加载远程文件。
/**
* 监控流程:
* ①向词库服务器发送Head请求
* ②从响应中获取Last-Modify、ETags字段值,判断是否变化
* ③如果未变化,休眠1min,返回第①步
* ④如果有变化,重新加载词典
* ⑤休眠1min,返回第①步
*/
public void run() {
//超时设置
RequestConfig rc = RequestConfig.custom().setConnectionRequestTimeout(10*1000)
.setConnectTimeout(10*1000).setSocketTimeout(15*1000).build();
HttpHead head = new HttpHead(location);
head.setConfig(rc);
//设置请求头
if (last_modified != null) {
head.setHeader("If-Modified-Since", last_modified);
}
if (eTags != null) {
head.setHeader("If-None-Match", eTags);
}
CloseableHttpResponse response = null;
try {
response = httpclient.execute(head);
//返回200 才做操作
if(response.getStatusLine().getStatusCode()==200){
if (((response.getLastHeader("Last-Modified")!=null) && !response.getLastHeader("Last-Modified").getValue().equalsIgnoreCase(last_modified))
||((response.getLastHeader("ETag")!=null) && !response.getLastHeader("ETag").getValue().equalsIgnoreCase(eTags))) {
// 远程词库有更新,需要重新加载词典,并修改last_modified,eTags
Dictionary.getSingleton().reLoadMainDict();
last_modified = response.getLastHeader("Last-Modified")==null?null:response.getLastHeader("Last-Modified").getValue();
eTags = response.getLastHeader("ETag")==null?null:response.getLastHeader("ETag").getValue();
}
}else if (response.getStatusLine().getStatusCode()==304) {
//没有修改,不做操作
//noop
}else{
logger.info("remote_ext_dict {} return bad code {}" , location , response.getStatusLine().getStatusCode() );
}
} catch (Exception e) {
logger.error("remote_ext_dict {} error!",e , location);
}finally{
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
1.创建es索引,添加mapping,给字段添加ik分词器配置
private static TransportClient client;
static {
try{
// 1 设置连接的集群名称
Settings settings = Settings.builder().put("cluster.name", "MYELK").build();
// 2 连接集群
client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("ELK05"), 9300));
}catch (Exception e){
}
}
/**
* @Description: 创建索引
* @author tang
* @date 2019/2/6 14:53
*/
public static void createIndex(String indexNames,String type) throws Exception{
XContentBuilder mapping = createMapping(indexNames, type);
// 1 创建索引.
CreateIndexRequestBuilder indexRequestBuilder = client.admin().indices().prepareCreate(indexNames).addMapping(type,mapping);
indexRequestBuilder.get();
}
/**
* @Description: 创建mapping 并配置分词器
* @author tang
* @date 2019/3/9 19:39
*/
public static void addMapping(String index,String type) throws Exception {
// 1设置mapping
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.startObject(type)
.startObject("properties")
.startObject("spu_name")
.field("type", "text")
.field("analyzer", "ik_max_word")
.field("search_analyzer","ik_smart")
.endObject()
.startObject("shop_name")
.field("type", "text")
.field("analyzer", "ik_max_word")
.field("search_analyzer","ik_smart")
.endObject()
.endObject()
.endObject()
.endObject();
// 2 添加mapping
PutMappingRequest mapping = Requests.putMappingRequest(index).type(type).source(builder);
client.admin().indices().putMapping(mapping).get();
// 3 关闭资源
client.close();
}
public static void main(String[] args) throws Exception{
createIndex("item","2020-03-25");
//给index的type添加mapping,需要先创建索引先
addMapping("item","2020-03-28");
}
2.搜索内容:大厨小炒 名中 大厨和小炒两个词,说明es是有大厨小炒 切分成大厨和小炒两个词
3.在nginx上添加ik分词扩展词典
nginx配置:
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
root html;
index index.html index.htm;
}
}
把远程字典放在 nginx 跟目录 html下,如:
在谷歌浏览器上输入地址 :http://192.168.25.128/mydict.dic 检查是否能下载此文件
4.在es的ik分词器中配置文件 IKAnalyzer.cfg.xml配置远程扩展词典路径:
IK Analyzer 扩展配置
http://192.168.25.128/mydict.dic
5.把词语:大厨小炒 放到远程词典中,直接修改或覆盖ngix上的mydict.dic文件,ik分词器检查到远程文件有变化,则重新加载远程文件,不需要重启es服务器
6.再次搜索 大厨小炒 搜发现直接命中 大厨小炒 这一整个词,说明es是按 大厨、小炒、大厨小炒 来切分成三个单词了。