首先要创建一个网络,以便让 ES 和 Kibana 容器互联。
docker network create es-net
使用 Docker 拉取 Elasticsearch7.17.11 版本的镜像:
docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.11
拉取完镜像后使用 Docker 运行 ES 容器:
docker run -d \
--name es \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v es-data:/usr/share/elasticsearch/data \
-v es-plugins:/usr/share/elasticsearch/plugins \
--privileged \
--network es-net \
-p 9200:9200 \
-p 9300:9300 \
docker.elastic.co/elasticsearch/elasticsearch:7.17.11
注:
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m"
:设置堆大小(默认堆大小为 1GB1)-e "discovery.type=single-node"
:单节点模式-v es-data:/usr/share/elasticsearch/data
:挂载逻辑卷,绑定 ES 的数据目录-v es-plugins:/usr/share/elasticsearch/plugins
:挂载逻辑卷,绑定 ES 的插件目录--privileged
:授予逻辑卷访问权--network es-net
:加入一个名为 es-net 的网络中
运行成功后,在浏览器中访问对应 ip 的 9200 端口可看到 ES 的响应结果:
使用 Docker 拉取 Kibana7.17.11 版本的镜像:
docker pull docker.elastic.co/kibana/kibana:7.17.11
注:Kibana 版本应跟 Elasticsearch 版本保持一致。
拉取完镜像后使用 Docker 运行 Kibana 容器:
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
docker.elastic.co/kibana/kibana:7.17.11
注:
--network es-net
:加入一个名为 es-net 的网络中,与 Elasticsearch 在同一个网络中-e ELASTICSEARCH_HOSTS=http://es:9200"
:设置 Elasticsearch 的地址,因为 Kibana 已经与 Elasticsearch 在同一个网络,因此可以用容器名直接访问 Elasticsearch
运行成功后,在浏览器中访问对应 ip 的 5601 端口可看到:
可通过 Kibana 提供的 Dev Tools 来编写 DSL 语句操作 Elasticsearch :
在 Dev Tools 界面中,在左边编写 DSL 语句,在右边查看响应结果。
使用以下 DSL 语句进行测试:
GET /
在这个界面编写 DSL 语句具有自动补全功能。
在 Kibana 的 Dev Tools 里通过以下 DSL 语句来测试 ES 默认的 standard 分词器2:
GET /_analyze
{
"analyzer" : "standard",
"text" : "分词器分词效果测试"
}
测试结果:
{
"tokens" : [
{
"token" : "分",
"start_offset" : 0,
"end_offset" : 1,
"type" : "" ,
"position" : 0
},
{
"token" : "词",
"start_offset" : 1,
"end_offset" : 2,
"type" : "" ,
"position" : 1
},
{
"token" : "器",
"start_offset" : 2,
"end_offset" : 3,
"type" : "" ,
"position" : 2
},
{
"token" : "分",
"start_offset" : 3,
"end_offset" : 4,
"type" : "" ,
"position" : 3
},
{
"token" : "词",
"start_offset" : 4,
"end_offset" : 5,
"type" : "" ,
"position" : 4
},
{
"token" : "效",
"start_offset" : 5,
"end_offset" : 6,
"type" : "" ,
"position" : 5
},
{
"token" : "果",
"start_offset" : 6,
"end_offset" : 7,
"type" : "" ,
"position" : 6
},
{
"token" : "测",
"start_offset" : 7,
"end_offset" : 8,
"type" : "" ,
"position" : 7
},
{
"token" : "试",
"start_offset" : 8,
"end_offset" : 9,
"type" : "" ,
"position" : 8
}
]
}
可以看到 ES 默认的 standard 分词器对中文分词不友好,所以需要配置对中文分词较友好的 IK 分词器3。
分词器的作用:
创建倒排索引时对文档分词
用户搜索时,对输入的内容分词
现在安装的 Elasticsearch 版本为 7.17.11,所以我们应该从 IK 分词器的 GitHub 仓库中找到对应的版本来进行下载,但目前 IK 分词器没有给出 7.17.11 的版本,因此我们只能先下载相近的版本,这里选择下载 IK 分词器的 7.17.7 版本,下载地址如下:
https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.17.7/elasticsearch-analysis-ik-7.17.7.zip
IK 分词器是通过插件的形式来安装到 Elasticsearch 中的,所以需要知道 Elasticsearch 的 plugins 目录位置,而我们运行 Elasticsearch 容器时使用了数据卷挂载,因此需要查看 Elasticsearch 的数据卷目录,通过以下命令查看:
docker volume inspect es-plugins
可以看到 plugins
目录被挂载到了 /var/lib/docker/volumes/es-plugins/_data
目录中。
我们需要将下载好的 IK 分词器压缩包里面的文件解压到一个名为 ik 的文件夹中,并上传 ik 文件夹到 plugins
挂载的目录下。
需要注意 的是:因为 Elasticsearch 版本和 IK 分词器版本不一致,所以加载 IK 分词器前需要修改 ik 文件夹中的 plugin-descriptor.properties
文件里面的 elasticsearch.version
为 7.17.11,不然 Elasticsearch 启动时加载 IK 分词器会报错4。
保存修改后重启 ES:
docker restart es
查看日志
docker logs -f es
可以看到 IK 分词器已经被加载。
在 Kibana 的 Dev Tools 里通过以下 DSL 语句进行测试:
GET /_analyze
{
"analyzer" : "ik_smart",
"text" : "分词器分词效果测试"
}
测试结果如下:
{
"tokens" : [
{
"token" : "分词器",
"start_offset" : 0,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "分词",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "效果",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "测试",
"start_offset" : 7,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 3
}
]
}
在 Kibana 的 Dev Tools 里通过以下 DSL 语句进行测试:
GET /_analyze
{
"analyzer" : "ik_max_word",
"text" : "分词器分词效果测试"
}
测试结果如下:
{
"tokens" : [
{
"token" : "分词器",
"start_offset" : 0,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "分词",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "器",
"start_offset" : 2,
"end_offset" : 3,
"type" : "CN_CHAR",
"position" : 2
},
{
"token" : "分词",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "效果",
"start_offset" : 5,
"end_offset" : 7,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "测试",
"start_offset" : 7,
"end_offset" : 9,
"type" : "CN_WORD",
"position" : 5
}
]
}
ik_max_word: 会将文本做最细粒度的拆分,会穷尽各种可能的组合,适合 Term Query。好处是搜索到的概率可能较高,缺点是分的词多了,占用内存空间会更多;
ik_smart: 会做最粗粒度的拆分,适合 Phrase 查询。好处是分的词少了,将来查询更多的数据效率会更高一点,缺点是搜索到的概率可能较低。
所以,在这两种方式的选择上,需要在内存占用、查询效率、搜索到的概率等方面进行考虑。
这里选择使用 百度停用词表 来作为停用词典,按照自己的需求也可以选择哈工大停用词表等5。
可访问下面的链接来下载百度停用词表(baidu_stopwords.txt):
https://github.com/goto456/stopwords/blob/master/baidu_stopwords.txt
下载好 baidu_stopwords.txt 文件后,需要将文件另存为 baidu_stopwords.dic ,要 注意文件编码得是 UTF-8 。
在 Kibana 的 Dev Tools 里通过以下 DSL 语句进行测试:
GET /_analyze
{
"analyzer" : "ik_smart",
"text" : "停用词测试,的,地,得"
}
测试结果如下:
{
"tokens" : [
{
"token" : "停",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "用词",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "测试",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "的",
"start_offset" : 6,
"end_offset" : 7,
"type" : "CN_CHAR",
"position" : 3
},
{
"token" : "地",
"start_offset" : 8,
"end_offset" : 9,
"type" : "CN_CHAR",
"position" : 4
},
{
"token" : "得",
"start_offset" : 10,
"end_offset" : 11,
"type" : "CN_CHAR",
"position" : 5
}
]
}
可以看到如果没有去停用词,那么“的、地、得”这些词也会被输出出来。
在 plugins
挂载的目录下,进入之前上传的 ik 文件夹中,再进入 config 文件夹下修改 IKAnalyzer.cfg.xml
文件,将停用词典的文件名填入到指定位置:
修改配置文件并保存后重启 ES:
docker restart es
查看日志
docker logs -f es
在 Kibana 的 Dev Tools 里通过以下 DSL 语句进行测试:
GET /_analyze
{
"analyzer" : "ik_smart",
"text" : "停用词测试,的,地,得"
}
测试结果如下:
{
"tokens" : [
{
"token" : "停",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "用词",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "测试",
"start_offset" : 3,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 2
}
]
}
可以看到,“的、地、得”这三个字已经不输出了,说明停用词典已经配置好了。
官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html
https://www.elastic.co/guide/en/kibana/7.17/docker.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/indices-analyze.html
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/heap-size.html ↩︎
https://www.elastic.co/guide/en/elasticsearch/reference/7.17/analysis-standard-tokenizer.html ↩︎
https://github.com/medcl/elasticsearch-analysis-ik#readme ↩︎
https://github.com/medcl/elasticsearch-analysis-ik/issues/996 ↩︎
https://github.com/goto456/stopwords ↩︎