一、ElasticSearch 简介
持续更新
ElasticSearch 是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据,本身扩展性很好,可以扩展上百台服务器,处理 PB 级别数据。
Elasticsearch 也可以使用 Java 开发并使用 Lucene 作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTFUL API 来隐藏 lucence 的复杂性,从而让全文搜索变得简单。
二、Docker 安装 Elasticsearch
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -d elasticsearch:7.16.2
安装中文分词器
方法一:
1. 进入容器
docker exec -it elasticsearch bash
2. 进入plugins 目录
cd /usr/share/elasticsearch/plugins
3. 安装中文分词器
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.16.2/elasticsearch-analysis-ik-7.16.2.zip
4. 退出容器重启 elasticsearch
docker restart elasticsearch
方法二:
前往这里下载对应版本的 ik 分词器,进入容器
# 1. 复制ik分词器到容器内
docker cp elasticsearch-analysis-ik-7.16.2.zip 7c0ae984c060:/usr/share/elasticsearch/plugins
# 2. 进入容器
docker exec -it elasticsearch bash
# 3. 进入plugins 目录
cd /usr/share/elasticsearch/plugins
# 4. 新建 ik 文件夹解压进去
mkdir ik
unzip elasticsearch-analysis-ik-7.16.2.zip -d ./ik
# 5. 删除 elasticsearch-analysis-ik-7.16.2.zip
rm -rf elasticsearch-analysis-ik-7.16.2.zip
# 6. 退出容器重启 elasticsearch
docker restart elasticsearch
三、基本概念
-
Cluster 集群与 Node 节点
ES 可以作为一个单独的搜索服务器,不过,为了处理大量数据,实现容错和高可用性,ES 可以运行在许多互相合作的服务器上,这些服务器的集合称为集群。每一个组成的服务器称为一个节点(node)。
-
Shard 分片
当有大量文档时,由于内存的限制,磁盘处理能力不足。无法足够快的响应客户的请求,一个节点不够用,这时,数据可以分为较小的分片,每个分片放到不同的服务器上。当你查询的索引分布在多个分片上时,ES 会把查询发送到每个相关的分片,并将结果组合在一起,而应用程序并不知道分片的存在。
-
Index
ES 会索引所有字段,经过处理后写入到一个反向索引(Inverted Index)。查找数据的时候直接查询该索引。
所以,ES 数据管理的顶层单位就叫做 Index(索引)。它是单个数据库的同义词,每个 Index(即数据库)的名字必须是小写。
下面的命令是查看当前节点的所有 Index
curl -X GET 'http://localhost:9200/_cat/indices?v'
-
Document
Index 里面单条记录称为 Docment(文档),许多条文档构成了 Index。
Document 使用 JSON 格式表示,下面是一个例子。
{ "user": "sixkery", "title": "es", "desc": "分布式搜索引擎" }
-
Type(可不看)
Document 可以分组,比如
weather
这个 Index 里面,可以按城市分组(北京和上海),也可以按气候分组(晴天和雨天)。这种分组就叫做 Type,它是虚拟的逻辑分组,用来过滤 Document。不同的 Type 应该有相似的结构(schema),举例来说,
id
字段不能在这个组是字符串,在另一个组是数值。这是与关系型数据库的表的一个区别。性质完全不同的数据(比如products
和logs
)应该存成两个 Index,而不是一个 Index 里面的两个 Type(虽然可以做到)。下面的命令可以列出每个 Index 所包含的 Type。
$ curl 'http://localhost:9200/_mapping?pretty=true'
根据规划,Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type,提供一个默认的 type 是 _doc。
四、新建和删除 Index
新建 Index,可以直接向 ES 发送 PUT 请求,比如新建 userInfo
的索引。
curl -X PUT 'http://localhost:9200/userInfo'
服务器返回一个 JSON 对象,里面的acknowledged
字段表示操作成功。
{
"acknowledged":true,
"shards_acknowledged":true,
"index":"userInfo"
}
然后发送 delete 请求,删除这个索引
curl -X DELETE 'http://localhost:9200/userInfo'
五、新建索引
新建一个指定中文分词器的索引,这里需要指定分词的字段,基本上,凡是需要搜索的中文字段,都需要设置一下。
curl -X PUT 'http://localhost:9200/accounts' \
--header 'Content-Type: application/json' \
--data-raw '{
"mappings": {
"properties": {
"user": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"title": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
"desc": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}
}'
上面代码中创建了一个名为 accounts 的索引,有三个字段:user 、title、desc
。这三个字段都是中文,而且类型都是文本(text),所以需要指定中文分词器,不能使用默认的英文分词器。
"user": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
},
# 这里 analyzer 是字段文本的分词器,search_analyzer 是搜索词的分词器。ik_max_word 分词器是插件 ik 提供的,可以对文本进行最大数量的分词。
六、数据操作
6.1 新增数据
向指定索引发送 POST 请求就可以在 Index 中新增数据。
curl -X POST 'http://localhost:9200/accounts/_doc' \
--header 'Content-Type: application/json' \
--data-raw '{
"user": "sixkery",
"title": "es工程师",
"desc": "代码写的好"
}'
服务器返回的 JSON 对象,会给出 Index、Type、Id、Version 等信息。
{
"_index": "accounts",
"_type": "_doc",
"_id": "-xxs0H8B-7-agoquNFaJ",
"_version": 1,
"result": "created",
"_shards": { "total": 2, "successful": 1, "failed": 0 },
"_seq_no": 0,
"_primary_term": 1
}
上面没有指定数据的 _id ,es 会自动生成一个随机的字符串。如果指定数据的 _id 的话可以发送 put 请求
curl --location --request PUT 'http://localhost:9200/accounts/_doc/1' \
--header 'Content-Type: application/json' \
--data-raw '{
"user": "果果",
"title": "捣蛋猫",
"desc": "猫粮快拿来"
}'
6.2 查看数据
向索引发送 GET 请求,就可以查看这条数据:
curl -X GET 'http://localhost:9200/accounts/_doc/1?pretty=true'
{
"_index" : "accounts",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"user" : "果果",
"title" : "捣蛋猫",
"desc" : "猫粮快拿来"
}
}
url 请求查看索引 accounts id 为 1 的数据,参数 pretty=true
表示以易读的方式返回。返回的数据中 found 表示查询成功,_source
字段返回原始记录。
6.3 更新记录
更新记录就是使用 PUT 请求,重新发送一次数据。从返回的数据中发现,记录的 Id 没变,但是版本(version)从1
变成2
,操作类型(result)从created
变成updated
,因为这次不是新建记录
curl --location --request PUT 'http://localhost:9200/accounts/_doc/1' \
--header 'Content-Type: application/json' \
--data-raw '{
"user": "果果",
"title": "捣蛋猫",
"desc": "猫粮快拿来,这是更新数据"
}'
{
"_index":"accounts",
"_type":"_doc",
"_id":"1",
"_version":2,
"result":"updated",
"_shards":{"total":2,"successful":1,"failed":0},
"_seq_no":2,
"_primary_term":1
}
七、查询
7.1 查询所有记录
使用 GET 方法,直接请求/Index/Type/_search
,就会返回所有记录。
curl -X GET 'http://localhost:9200/accounts/_doc/_search?pretty=true'
{
"took": 32,
"timed_out": false,
"_shards": {"total": 1,"successful": 1,"skipped": 0,"failed": 0},
"hits": {
"total": {"value": 2,"relation": "eq"},
"max_score": 1.0,
"hits": [
{
"_index": "accounts",
"_type": "_doc",
"_id": "-xxs0H8B-7-agoquNFaJ",
"_score": 1.0,
"_source": {"user": "sixkery","title": "es工程师","desc": "代码写的好"}
},
{
"_index": "accounts",
"_type": "_doc",
"_id": "1",
"_score": 1.0,
"_source": {"user": "果果","title": "捣蛋猫","desc": "猫粮快拿来,这是更新数据"}
}
]
}
}
上面代码中,返回结果的 took
字段表示该操作的耗时(单位为毫秒),timed_out
字段表示是否超时,hits
字段表示命中的记录,里面子字段的含义如下。
total
:返回记录数,本例是2条。max_score
:最高的匹配程度,本例是1.0
。hits
:返回的记录组成的数组。
返回的记录中,每条记录都有一个_score
字段,表示匹配的程序,默认是按照这个字段降序排列。
7.2 全文检索
感谢阮一峰博客。