本文主要有以下内容:
- ElasticSearch、kibana、cerebro 软件的安装
- ElasticSearch 的基本概念
- ElasticSearch 的简单操作
本服务器环境为Ubuntu 20.04
,仅保证在该系统环境下正常运行。
软件安装
ElasticSearch 的安装:
# 下载软件,也可以在windows平台下载后 通过scp命令上传至服务器。
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.13.0-linux-x86_64.tar.gz
mkdir ES
mv elasticsearch-7.13.0-linux-x86_64.tar.gz ES
cd ES
# 解压文件
tar xvf elasticsearch-7.13.0-linux-x86_64.tar.gz
# 会在单机上安装多个ES节点,现在先命名为es_node1
mv elasticsearch-7.13.0 es_node1
修改elasticsearch.yml
cd es_node1
echo -e 'n' >> config/elasticsearch.yml
echo 'cluster.name: my_app' >> config/elasticsearch.yml
echo 'node.name: my_node_1' >> config/elasticsearch.yml
echo 'path.data: ./data' >> config/elasticsearch.yml
echo 'path.logs: ./logs' >> config/elasticsearch.yml
echo 'http.port: 9211' >> config/elasticsearch.yml
echo 'network.host: 0.0.0.0' >> config/elasticsearch.yml
echo 'discovery.seed_hosts: ["localhost"]' >> config/elasticsearch.yml
echo 'cluster.initial_master_nodes: ["my_node_1"]' >> config/elasticsearch.yml
查看配置文件cat elasticsearch.yml
,配置文件如下图:
继续修改jvm.option
的参数:
echo -e 'n' >> config/jvm.options
# 设置堆内存最小值
echo '-Xms1g' >> config/jvm.options
# 设置堆内存最大值
echo '-Xmx1g' >> config/jvm.options
echo -e 'nvm.max_map_count=262144' >> /etc/sysctl.conf
修改完成后,进入es_node1
的bin
目录下,运行软件!
cd bin/
# 运行
./elasticsearch
# 后台运行
./elasticsearch -d
安装 kibana,该软件提供了一个dashboard供我们操作ES,把操作可视化:
cd ES
# 下载
wget https://artifacts.elastic.co/downloads/kibana/kibana-7.13.0-linux-x86_64.tar.gz
tar xvf kibana-7.13.0-linux-x86_64.tar.gz
# 重命名
mv kibana-7.13.0-linux-x86_64 kibana
cd kibana
echo -e 'nserver.host: "0.0.0.0"' >> config/kibana.yml
echo -e 'nelasticsearch.hosts: ["http://localhost:9211"]' >> config/kibana.yml
# 运行
./cerebro >> run.log 2>&1 &
安装 cerebro,该软件提供了对ES的管理功能,可以通过此软件查看 ES 集群的状态。
cd ES
wget https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro-0.9.4.tgz
tar xvf cerebro-0.9.4.tgz
mv cerebro-0.9.4 cerebro
cd cerebro
sed -i 's/server.http.port = ${?CEREBRO_PORT}/server.http.port = 9800/g' conf/application.conf
echo -e 'nhosts = [
{
host = "http://localhost:9211"
name = "my_app"
}
]' >> conf/application.conf
安装好后分别启动进程,通过ip:端口号
就可以访问,如果无法访问请放开防火墙
ES 集群配置:
复制 es_node1 并命名为es_node2,删除 es_node2 中的 data 和log 目录。修改配置如下图 es_node1 配置
es_node2 配置如下:
分别启动 es_node1 和 es_node2, 通过 cerebro 就可以看见集群相关信息:
集群层面的基本概念
集群:由多个协同工作的 ES 实例组合成的集合称为集群。
节点:单个 ES 的服务实例叫做节点,本质上就是一个 Java 进程。
主节点(Master): 主节点在整个集群是唯一的,Master 从有资格进行选举的节点(Master Eligible)中选举出来。
数据节点(Data Node) :其负责保存数据,要扩充存储时候需要扩展这类节点。
协调节点(Coordinating Node) :负责接受客户端的请求,将请求路由到对应的节点进行处理,并且把最终结果汇总到一起返回给客户端。
预处理节点(Ingest Node) :预处理操作允许在写入文档前通过定义好的一些 processors(处理器)和管道对数据进行转换。
部落节点(Tribe Node) :部落节点可以连接到不同集群,并且支持将这些集群当成一个单独的集群处理。
Hot & Warm Node:不同硬件配置的 Data Node,用来实现 Hot & Warm 架构的节点,有利于降低集群部署成本。
分片:分片(Shard)是 ES 底层基本的读写单元,分片是为了分割巨大的索引数据,让读写可以由多台机器来完成,从而提高系统的吞吐量。 相当于数据页。
副本:为了保证数据可靠性,一般分布式系统都会对数据进行冗余备份,这个备份就是副本。ES将数据副本分为主从两类型:主分片(primary shard)和副分片(replica shard) 。
数据层面的基本概念
索引:一类相似性文档的集合,类似于数据库中的表。
Mapping:相当于 ddl 语句,即定义了索引里的文档到底有哪些字段及这些字段的类型
文档:相当于数据库表中的一条记录,只不过在ES中称之为文档
字段:相当于数据库中的列,定义在 Mapping 中。用于描述文档。
下面就是一个索引的示例:
在 kibana 的 Dev Tools 中输入下面的命令:
# 创建 books 索引
PUT books_index
{
"mappings": {
"properties": {
"book_id": {
"type": "keyword"
},
"book_name": {
"type": "text"
},
"author": {
"type": "keyword"
},
"book_intro": {
"type": "text"
}
}
},
# 指定 3 个分片 每个分片有 1 个副本
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
# 返回结果
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "books"
}
上面的索引就相当于有三个主分片去存储数据,每一个分片都有一个副本:通过GET books_index
查看内容:
实现代表主分片,虚线代表副分片。
词项(term):将全文本内容分词后得到的词语就是词项Nobody knows it better than me
在分词器分词后得到nobody
、knows
、 it
、better
、than
、me
。是最小的单位。
注意:被分词后,会统一变为小写。
ES的基本操作
索引相关
- 新建索引
- 删除索引
删除索引
删除操作很简单,如下
DELETE books_index
文档相关
文档操作有如下几种:
- 新建文档
- 更新文档
- 删除文档
- 获取文档
- 批量获取文档
新建文档
ES 提供了两种创建文档的方式,一种是使用 Index API 索引文档,一种是使用 Create API 创建文档。
使用 Index API 创建新增文档如下:这种方式创建文档如果 id 已经存在则会删除原文档在存储新文档,类似于HashMap的put操作
# 使用 Index API 索引文档
PUT books_index/_doc/1
{
"book_id": "20230807",
"book_name": "Java从入门到入坟",
"author": "Master Yi",
"book_intro": "javaer will lose jobs at 35"
}
使用 Create API 创建文档:这种方式有两种写法,post 和 put
PUT books_index/_create/2
{
"book_id": "20230808",
"book_name": "Java Virtual Machine",
"author": "Master Zhou",
"book_intro": "At the age of 35, Javaer will go to deliver food "
}
# 使用 POST 的方式,不需要指定文档 ID, 系统自动生成
POST books_index/_doc
{
"book_id": "20230809",
"book_name": "Javaer从删库到跑路",
"author": "Master su",
"book_intro": "请你记住,无论什么时候你总要保证人和代码总有一个能跑!"
}
更新文档
# 更新文档
POST books_index/_update/2
{
"doc": {
"book_name": "Java虚拟机(译本)",
"book_intro": "向社会输送35岁以上的高质量精英人才"
}
}
#结果
{
"_index" : "books_index",
"_type" : "_doc",
"_id" : "2",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
删除文档
# 删除文档 2
DELETE books_index/_doc/2
# 结果
{
"_index" : "books_index",
.....
"result" : "deleted",
......
}
获取文档
可以获取单个文档和多个文档。
获取单个文档
# 使用 GET API 获取单个文档的内容
GET books_index/_doc/1
获取多个文档
# 1:在 body 中指定 index
GET /_mget
{
"docs": [
{ "_index": "books_index", "_id": "1" },
{ "_index": "books_index", "_id": "2" },
# 这个id是我们创建时没有指定,es给我们生成的
{"_index":"books_index","_id":"AreuzokB2gsE8wXSZS23"}
]
}
# 2:直接指定 index
GET /books_index/_doc/_mget
{
"docs": [
{ "_id": "1" },
{ "_id": "2" }
]
}
# 3:也可以简写为一下例子
GET /books_index/_mget
{
"ids" : ["1", "2","AreuzokB2gsE8wXSZS23"]
}
全文搜索
match
匹配查询:匹配查询可以处理全文本、精确字段(日期、数字等)
# 匹配查询 查询出两本书 ,如果id为2的没有删除的话
POST books_index/_search
{
"query": {
"match": {
"book_name": "Java虚拟机(译本)"
}
}
}
会将"Java虚拟机(译本)
进行分词,分成java
和虚
、拟
、机
、译
、本
六个词,进行(书名)全文匹配
# 只查询出 Java虚拟机这本书
POST books_index/_search
{
"query": {
"match": {
"book_name": {
"query": "Java虚拟机(译本)",
"operator": "and",
"minimum_should_match": "75%"
}
}
}
}
可通过如下指令查看分词结果:
GET _analyze
{
"analyzer":"standard",
"text":"Java虚拟机(译本)"
}
match:
- operator,参数值可以为 "or" 或者 "and" 来控制检索词项间的关系,默认值为 "or"。所以上面例子中,只要书名中含有 "linux" 或者 "architecture" 的文档都可以匹配上。
- minimum_should_match,可以指定词项的最少匹配个数,其值可以指定为某个具体的数字,但因为我们无法预估检索内容的词项数量,一般将其设置为一个百分比。
# 匹配查询
POST books/_search
{
"query": {
"match": {
"name": {
"query": "Dive linux kernea architecture",
"operator": "or",
"minimum_should_match": "75%"
}
}
}
}
全部查询:查询出所有书籍:
POST books_index/_search
{
"query": {
"match_all": {}
}
}
match phrase(短语匹配)
短语匹配会将检索内容进行分词,这些词语必须全部出现在被检索内容中,并且顺序必须一致,默认情况下这些词都必须连续。
可以使用 slop 参数来指定词项间的距离差值,即两个词项中可以含有多少个其他不相关的词语,slop 默认是 0。
# 短语匹配
POST books_index/_search
{
"query": {
"match_phrase": {
"name": "javaeer" #换成java 将会匹配两本书
}
}
}
match phrase prefix(短语前缀匹配)
# 匹配以 "Javaer" 开头的短语
POST books_index/_search
{
"query": {
"match_phrase_prefix": {
"book_name": "Javaer"
}
}
}
# 匹配以 "jav" 开头的短语,每个分片最多匹配 2 个
POST books_index/_search
{
"query": {
"match_phrase_prefix": {
"book_name": {
"query": "jav",
"max_expansions": 2
}
}
}
}
multi-match
multi-match API 构建在 match 查询的基础上,可以允许在多个字段上执行相同的查询。
# multi match API:
GET /books_index/_search
{
"query": {
"multi_match": {
"query": "javaer",
"fields": [
"book_nam*",
"book_intro^2"
]
}
}
}
fields 参数是一个列表,里面的元素是需要查询的字段名字。fields 中的值既可以支持以通配符方式匹配文档的字段,又可以支持提升字段的权重。如 "book_nam*" 就是使用了通配符匹配的方式,其可以匹配到书名(book_name)字段。而 "book_intro^2" 就是对书本简介字段(book_intro)的相关性评分乘以 2。