elasticsearch
Elasticsearch是一个基于Lucene的搜索服务器,也是属于NoSQL阵营的数据库。它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口提供给我们操作的。Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种流行的企业级搜索引擎。除了es以外, Sphinx 、迅搜、Zebra、Solr 、Whoosh。
官网:https://www.elastic.co/cn/elasticsearch/
中文文档:https://www.elastic.co/guide/cn/index.html
最新版本:8.0 版本。目前在市面上常用的版本是6.x和7.x,甚至是5.x。
安装elasticsearch
支持单点部署和集群部署。
x# 从课件的素材中找到es的镜像压缩包,复制到ubuntu桌面下,执行以下命令
# sudo docker load -i ~/Desktop/elasticsearch.7.13.4.tar.gz
podman load -i ~/Desktop/elasticsearch.7.13.4.tar.gz
# 也可以不执行上面的操作,直接run可以让docker从官网拉取es镜像。
# sudo docker run --name elasticsearch --restart=always -it -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms256m -Xmx256m" -e "discovery.type=single-node" elasticsearch:7.13.4
podman run --name elasticsearch -it -p 9200:9200 -p 9300:9300 -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -e "discovery.type=single-node" elasticsearch:7.13.4
参数说明
xxxxxxxxxx
--name elasticsearch
设置当前容器的容器名称为elasticsearch
--restart=always
设置容器开机自启,即便物理机关机重启了,docker在启动以后也会自动帮我们把当前容器启动起来。
-it 设置当前容器以交互式终端的模式运行
-p 9200:9200
设置端口影射,<物理机端口>:<容器端口>
表示访问了当前物理机的9200,相当于访问了当前容器的9200端口
-p 9300:9300
设置端口影射,<物理机端口>:<容器端口>
表示访问了当前物理机的9300,相当于访问了当前容器的9300端口
-e ES_JAVA_OPTS="-Xms256m -Xmx256m"
设置环境变量,变量名为ES_JAVA_OPTS,这个变量是启动elasticsearch的关键。
表示设置java环境的最小和最大使用内存,内存不足,elasticsearch是无法启动的,所以此处设置为最小内存必须在256M以上
-e "discovery.type=single-node"
设置环境变量,变量名discovery.type
discovery.type 表示当前elasticsearch的运作模式为single-node,表示单机部署/单点部署
elasticsearch:7.13.4
设置当前容器的镜像名和版本号
浏览器访问:https://127.0.0.1:9200
要基于es实现全文搜索,可以参考以下文档了解关于全文搜索的内容。
https://www.elastic.co/guide/cn/elasticsearch/guide/current/full-text-search.html
全文搜索的实现,必须依靠es内部调用分词器对大文本语句进行词性分析,拆词,给每一个单词单独构建一个索引。
默认情况下,es只提供了标准分析器和关键字分析器,都是只能针对英文进行分词。
xxxxxxxxxx
所谓的分词,就是把一段文本中的所有词组,按提供的字典,进行词组拆分。
例如:welcome to beijing!
welcome 动词 0 6
to 谓语 0 6
beijing 名词 0 6
接下来,我们就可以通过postman测试。
注意:es提供的9200是restful api接口的端口,以https形式访问(es8.x默认是https),9300端口是Api对服务器的管理端口。
xxxxxxxxxx
post https://127.0.0.1:9200/_analyze?pretty
使用elasticsearch提供的标准分词器和关键字分词器的。
xxxxxxxxxx
{
"analyzer":"standard",
"text":"我是中国人"
}
xxxxxxxxxx
{
"analyzer":"keyword",
"text":"我是中国人"
}
ik中文分词器
默认情况下,elasticsearch是外国开发的,所以本身对于中文分词构建分词索引的支持是比较差的。所以我们需要在elasticsearch软件中新增一个支持中文全文索引和对中文进行分词的插件,叫ik分词器。
注意:IK分词器插件的版本必须与elasticsearch的版本号同步。否则安装失败!
文档:https://github.com/medcl/elasticsearch-analysis-ik/releases
把IK分词器解压并复制到elasticsearch容器的/usr/share/elasticsearch/plugins目录下
xxxxxxxxxx
unzip ~/Desktop/elasticsearch-analysis-ik-7.13.4.zip -d ~/Desktop/ik-7.13.4
podman cp ~/Desktop/ik-7.13.4 elasticsearch:/usr/share/elasticsearch/plugins
podman stop elasticsearch
podman start elasticsearch
注意:elasticsearch内部极其复杂,所以启动容器以后需要等待1分钟左右才对外提供搜索服务。
接下来,我们就可以通过postman测试。
注意:es提供的9200是restful api接口的端口,以https形式访问(es8.x默认是https),9300端口是Api对服务器的管理端口。
xxxxxxxxxx
post https://127.0.0.1:9200/_analyze?pretty
基于智能分词模式来查询分析词性,json数据
xxxxxxxxxx
{
"analyzer":"ik_smart",
"text":"我是中国人"
}
基于最大分词模式来查询分析词性,json数据
xxxxxxxxxx
{
"analyzer":"ik_max_word",
"text":"我是中国人"
}
elasticsearch-head
elasticsearch-head 是用于监控 Elasticsearch 状态的客户端插件,包括数据可视化、执行增删改查操作等。不过开发中我们一般使用elasticsearch-head来查看elasticsearch的数据而已,真正对elasticsearch进行增删查改操作一般我们使用kibana或者postman或者编程语言实现的客户端来完成。
我们可以通过docker安装elasticsearch-head来对Elasticsearch 进行界面化管理。
xxxxxxxxxx
# 拉取镜像
# sudo docker pull mobz/elasticsearch-head:5
podman pull mobz/elasticsearch-head:5
# 创建容器[create不会自动运行容器,run会运行容器]
# sudo docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
podman create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
# 启动容器
# sudo docker start elasticsearch-head
podman start elasticsearch-head
访问elasticsearch-head:https://127.0.0.1:9100/,会发现无法连接elasticsearch,原因是因为跨域问题导致。
解决方案:修改容器elasticsearch中的elasticsearch.yml文件增加跨域支持即可。
xxxxxxxxxx
# sudo docker cp elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml ~/Desktop/elasticsearch.yml
podman cp elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml ~/Desktop/elasticsearch.yml
修改elasticsearch.yml内容,增加跨域支持,如下:
xxxxxxxxxx
cluster.name"docker-cluster"
network.host0.0.0.0
https.cors.enabled true
https.cors.allow-origin"*"
把elasticsearch.yml文件再次复制到容器elasticsearch中,并重启容器elasticsearch。
xxxxxxxxxx
# sudo docker cp ~/Desktop/elasticsearch.yml elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml
podman cp ~/Desktop/elasticsearch.yml elasticsearch:/usr/share/elasticsearch/config/elasticsearch.yml
修改容器elasticsearch-head的vendor.js让elasticsearch-head界面可以操作elasticsearch
xxxxxxxxxx
# sudo docker cp elasticsearch-head:/usr/src/app/_site/vendor.js ~/Desktop/vendor.js
podman cp elasticsearch-head:/usr/src/app/_site/vendor.js ~/Desktop/vendor.js
修改vendor.js内容,把6886行与7573行所在的"application/x-www-form-urlencoded"替换成"application/json;charset=UTF-8",并保存文件,复制回容器elasticsearch-head中。
xxxxxxxxxx
# sudo docker cp ~/Desktop/vendor.js elasticsearch-head:/usr/src/app/_site/vendor.js
podman cp ~/Desktop/vendor.js elasticsearch-head:/usr/src/app/_site/vendor.js
重启elasticsearch和elasticsearch-head容器
xxxxxxxxxx
# sudo docker stop elasticsearch
# sudo docker start elasticsearch
podman stop elasticsearch
podman start elasticsearch
# sudo docker stop elasticsearch-head
# sudo docker start elasticsearch-head
podman stop elasticsearch-head
podman start elasticsearch-head
kibana
Kibana是一个针对Elasticsearch的开源分析及可视化平台,用来搜索、查看交互存储在Elasticsearch索引中的数据。使用Kibana,可以通过各种图表进行高级数据分析及展示。
kibana的版本必须与Elasticsearch一致,所以我们安装的kibana也是7.13.4版本。
xxxxxxxxxx
# sudo docker pull kibana:7.13.4
# sudo docker run -d --name kibana -e ELASTICSEARCH_URL=https://127.0.0.1:9200 -p 5601:5601 --restart=always kibana:7.13.4
podman pull kibana:7.13.4
podman run -d --name kibana -p 5601:5601 kibana:7.13.4
修改让kibana能访问到Elasticsearch并完成汉化操作
xxxxxxxxxx
# sudo docker exec -it kibana bash
podman exec -it kibana bash
vi config/kibana.yml
kibana.yml中的内容需改如下:
xxxxxxxxxx
#
# ** THIS IS AN AUTO-GENERATED FILE **
#
# Default Kibana configuration for docker target
server.host"0"
# 注意:此处的IP地址替换为网卡地址,不能使用127.0.0.1或localhost,否则无法访问,可以通过ip a来查看
elasticsearch.hosts "https://192.168.233.129:9200"
monitoring.ui.container.elasticsearch.enabledtrue
i18n.locale"zh-CN"
修改完成以后,退出当前kibana容器,并重启kibana容器即可。
xxxxxxxxxx
# sudo docker stop kibana
# sudo docker start kibana
podman stop kibana
podman start kibana
等待1分钟左右,打开浏览器直接访问https://127.0.0.1:5601/,即可。
快速入门
核心概念
mysql中的数据是面向集合的,而Elasticsearch是面向文档的,以json格式存储数据的NoSQL数据库,也是一个全文搜索引擎。
Elasticsearch | 关系型数据库(如Mysql) |
---|---|
索引(Index) | 数据库(Database) |
类型(Type) | 表(Table) |
文档(Document) | 行,记录(Row,Record) |
字段(Field) | 列,字段(Column,Field) |
映射(Mapping) | 约束(Schema) |
注意:es中的类型在es7.x版本中已经没有,在后面的8.x版本中被彻底删除掉,与映射合并了。
倒排索引
倒排索引(Inverted Index),是Elasticsearch中的索引工作机制。倒排索引是区别于正排索引的概念:
- 正排索引:是以文档对象的唯一ID作为索引,以文档内容作为记录。
- 倒排索引:指的是将文档内容中的单词作为索引,将包含该词的文档ID作为记录。
Elasticsearch的工作流程如下,因为使用倒排索引产生的文档记录要比mysql数据行少多了,所以会比较快。
基本使用
Elasticsearch提供了retfulAPI风格操作接口给开发者对索引、类型、文档、字段、映射等进行增删查改操作。
索引操作
创建索引
请求格式:
xxxxxxxxxx
PUT /索引名称
使用postman发起创建
使用kibana的开发工具发送请求:
上面创建索引成功以后,可以通过Elasticsearch-head来查看索引信息。
也可以通过kibana提供的控制面板来查看索引信息。
类型映射[了解]
相当于在mysql中创建数据表时的字段类型
xxxxxxxxxx
# 必须保证!!!索引名称已经存在!索引名称就是库名,类型名称就是表名。
POST /索引名称/类型名称
{
"类型名称": { // 映射的类型名称,必须与地址栏上的类型名称一致!
"properties": { // 索引中文档的属性
"字段名": { // 属性名或字段名
"type": "text" // 属性值类型或字段类型,text表示文本,如商品标题
"index": "analyzed", // 索引类型
"analyzer": "ik_max_word" // 设置使用的分词器[最大分词模式]
},
"字段名": { // 属性名或字段名
"type": "text" // 属性值类型或字段类型,text表示文本,如商品标题
"index": "analyzed", // 索引类型
"analyzer": "standard" // 设置使用的分词器
},
"字段名": { // 属性名或字段名
"type": "text" // 属性值类型或字段类型,text表示文本,如商品标题
"index": "analyzed", // 索引类型
"analyzer": "standard" // 设置使用的分词器
}
}
}
}
kinana操作:
xxxxxxxxxx
POST /shop/goods
{
"goods": {
"properties": {
"id": {
"type": "long"
},
"title": {
"type": "text",
"index": "analyzed",
"analyzer": "ik_max_word"
},
"description": {
"type": "text",
"index": "analyzed",
"analyzer": "ik_smart"
},
"price": {
"type": "float"
},
"created_time":{
"type": "date",
"format":"yyyy-MM-dd HH:mm:ss"
}
}
}
}
使用kibana基于上面的goods映射类型创建文档数据并保存到elasticsearch
数据类型[了解]
elasticsearch中支持的常见字段数据类型:
类型 | 描述 |
---|---|
text | 字符串类型,可以模糊查询, 可以分词查询,不能聚合、排序 |
keyword | 字符串类型,只能精准查询, 不能分词查询,可以聚合、排序 |
long | 有符号的64位整数, 范围:[−263 ~ 263-1] |
Integer | 有符号的32位整数, 范围: [−231 ~ 231-1] |
short | 有符号的16位整数, 范围: [-32768 ~ 32767] |
byte | 有符号的8位整数, 范围: [-128 ~ 127] |
float | 32位单精度浮点数 |
double | 64位双精度浮点数 |
boolean | 布尔类型,支持使用字符串,数字等零值表示true/false |
date | 日期类型, |
date_nanos | 日期纳秒类型, |
binary | 二进制类型,Base64编码字符串的二进制值 |
Range | 范围类型,有integer_range, float_range, long_range, double_range, date_range等 |
array | 数组类型,ES中没有专门的数组类型, 直接使用[ ]定义即可,所有的成员的值必须是同一种数据类型 |
object | 对象类型,以json对象为结构 |
使用默认映射类型_doc代替上面手动创建的映射,es会内部自动推断字段类型。
xxxxxxxxxx
PUT /shop/_doc/文档ID
{
"name": "商品的标题",
"price": 18,
"created_time": "2022-01-10 22:00:31"
}
_doc
就是默认类型(default type),type在8.x版本会被彻底删除,以后使用默认类型_doc
替代即可。
查看索引
xxxxxxxxxx
GET /_cat/indices # 查看所有的索引的统计信息
GET /_cat/indices/索引名称 # 查看指定索引的统计信息
GET /索引名称 # 查看指定名称的索引信息
删除索引
xxxxxxxxxx
DELETE /索引名称
文档操作
请求方法/method | uri地址 | 描述 |
---|---|---|
PUT(创建,修改) | /索引名称/_doc/文档id | 创建文档(指定文档id) |
POST(创建) | /索引名称/_doc/文档id | 创建文档,如果uri地址只是以_doc结尾,文档id是随机生成的) |
POST(修改) | /索引名称/_doc/文档id/_update | 修改文档 |
DELETE(删除) | /索引名称/_doc/文档id | 删除文档 |
GET(查询) | /索引名称/_doc/文档id | 查询文档通过文档ID |
POST(查询) | /索引名称/_doc/文档id/_search | 查询数据 |
添加文档
方式1:使用PUT指定文档ID
xxxxxxxxxx
PUT /students/_doc/3
{
"title": "华为手机",
"description": "华为手机meta 50",
"cover": "1.png",
"price": "3999.00",
"created_time": "2022-01-10 22:00:31"
}
方式2:使用POST不指定文档ID
xxxxxxxxxx
POST /students/_doc
{
"title": "华为手机 meta 60",
"description": "华为手机meta 60",
"cover": "1.png",
"price": "3399.00",
"created_time": "2022-01-10 22:00:31"
}
方式3:通过POST指定文档ID
xxxxxxxxxx
POST /students/_doc/4
{
"title": "华为手机 meta 70",
"description": "华为手机meta 70",
"cover": "1.png",
"price": "3299.00",
"created_time": "2022-01-10 22:00:31"
}
修改文档
更新文档时文档的所有字段不管是否修改,都要全部填写
xxxxxxxxxx
POST /students/_doc/3
{
"title": "华为手机 meta 30",
"description": "华为手机meta 30",
"cover": "1.png",
"price": "2199.00",
"created_time": "2022-01-10 22:00:31"
}
也可以使用PUT请求方法。
xxxxxxxxxx
PUT /students/_doc/2
{
"title": "华为手机 meta 20",
"description": "华为手机meta 20",
"cover": "1.png",
"price": "2199.00",
"created_time": "2022-01-10 22:00:31"
}
删除文档
xxxxxxxxxx
DELETE /students/_doc/ZnHe-IIB2BprQjVH2OHS
查询文档
查询文档有三种方式:
- 主键查询:根据文档id查询
- 精确查询:根据关键词查询,也叫term查询 浪潮之巅 => 浪潮之巅 ≠> 浪潮之巅续集
- 匹配查询:根据输入的内容先对内容进行分词,再进行分词匹配查询索引 浪潮 => 浪潮之巅 => 浪潮之巅续集
准备数据
xxxxxxxxxx
POST /shop/_doc/1
{
"post_date":"2022-04-01",
"title":"浪潮之巅",
"content":"一部IT人非读不可,而非IT人也应该阅读的作品,讲故事的经典作品",
"author_id": 119
}
xxxxxxxxxx
POST /shop/_doc/2
{
"post_date":"2022-03-12",
"title":"人月神话",
"content":"一部IT人非读不可,而非IT人也应该阅读的作品,讲人与团队关系作品",
"author_id": 120
}
xxxxxxxxxx
POST /shop/_doc/3
{
"post_date":"2021-12-16",
"title":"代码之髓",
"content":"小日子过得不错的人写的作品,对代码中各种语言结构的实现进行揭秘",
"author_id": 110
}
主键查询
xxxxxxxxxx
GET /shop/_doc/3
精确查询
xxxxxxxxxx
POST /shop/_search
{
"query": {
"term": {
"字段名": {
"value": "字段值"
},
"字段名": {
"value": "字段值"
}
}
}
}
# 如果是text格式,无法精确查询的,只能匹配查询
kibana操作:
xxxxxxxxxx
POST /shop/_search
{
"query": {
"term": {
"author_id": {
"value": 119
}
}
}
}
匹配查询
查询所有
xxxxxxxxxx
POST /索引名称/_search
{
"query": { # 查询条件
"match_all": {} # 如果是match_all 表示查询所有
},
"sort": [ # 排序,注意:text无法使用排序,keyword才支持
# {"字段名":"排序规则,asc正序, desc倒序"}
{"title": "asc" }
],
"from": 0, # 查询起始下标,相当于SQL中的offset
"size": 2, # 限制结果数量,相当于SQL中的limit
"_source": ["title", "content"] # 字段投影,指定只返回部分字段,相当于SQL中的select,
}
kibana操作:
xxxxxxxxxx
POST /shop/_search
{
"query": {
"match_all": {}
},
"sort": {
"author_id": "desc"
},
"from": 0,
"size": 3,
"_source": ["title", "content"]
}
条件查询
格式:
xxxxxxxxxx
POST /索引名称/_search
{
"query": {
"match": {
"字段名": "查询条件值"
}
}
}
kibana的操作:
xxxxxxxxxx
POST /shop/_search
{
"query": {
"match": {
"title": "浪潮"
}
},
"sort": {
"author_id": "desc"
},
"from": 0,
"size": 3,
"_source": ["title", "content"]
}