Elasticsearch 基本概念及使用
- Elasticsearch 基本概念
- ES 的简介及使用场景
- ES 基本概念
- ES 与 Kibana 的安装
- Elasticsearch 分词器
- ES 内置分词器
- ik 分词器的安装和使用
- Elasticsearch 基本使用
- 索引操作
- 数据的增删改查
- DSL 查询
- 聚合查询
- 批量操作
Elasticsearch 基本概念
ES 的简介及使用场景
-
Elasticsearch 是一个分布式、高性能、高可用、可扩展、REST 风格的搜索和数据分析引擎;
-
Elasticsearch 搜索速度很快,是一个近实时的搜索引擎,从数据添加到可以搜索到该数据之间延迟极低;
-
Elasticsearch 可以配合 Logstash 和 Kibana 来做日志分析系统,一般在开发中也用作商城搜索引擎或物联网实时大数据的搜索;
ES 基本概念
下列表格描述了 Elasticsearch 与 MySQL 的核心概念的类比关系:
Elasticsearch | MySQL | 概述 |
---|---|---|
字段 | 列 | 字段对应数据库中的列,每个字段都有自己的数据类型 |
文档 | 数据行 | 文档是 ES 中可搜索数据的最小单元,其实际上就是一条 JSON 数据,由字段组成 |
类型 | 表 | 类型就是数据库中的表,从 7.0 版本开始,一个索引下就只能创建一个索引了(_doc) |
索引 | 库 | 索引就是数据库,它是一类文档的集合 |
节点 | 节点实际上就是一个实例,以保证高性能、高可用 | |
分片 | 类似数据库的分库分表,通过分片可以对数据进行垂直切分,每一个分片都是独立的且功能完整的索引,可以分布在任何的集群节点上 | |
副本 | 副本可以保证高可用,在出现问题时实现故障转移,ES 可以将索引的一个或者多个分片复制成副本分片 |
ES 与 Kibana 的安装
参考博客:Docker安装ElasticSearch和Kibana
ES 启动容器命令
docker run --name elasticsearch \
--restart=always \
-p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms84m -Xmx256m" \
-v /root/es/data:/usr/share/elasticsearch/data \
-v /root/es/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.17.7
Kibana 启动容器命令
docker run --name kibana \
--link=elasticsearch:elasticsearch \
-p 5601:5601 \
-d kibana:7.17.7
Elasticsearch 分词器
ES 内置分词器
ES 将 text 格式的字段按照分词器分词并进行索引的设置,这是其查询速度较快的根本原因。其内置了很多分词器,如下表所示。
分词器名称 | 规则 |
---|---|
standard | 默认的分词器,按照单词进行分类并进行小写处理 |
simple | 按照非字母进行切分,然后去除非字母并进行小写处理 |
stop | 按照停用词(the\a\is )进行过滤并进行小写处理 |
whitespace | 按照空格进行分词 |
keyword | 不进行分词处理,将文本视为一个整体 |
可以使用下列语句进行测试,观察不同分词器的区别
POST /_analyze
{
"analyzer":"standard",
"text":"basketball, League of Legends, my love"
}
POST /_analyze
{
"analyzer":"simple",
"text":"It is a tiger"
}
POST /_analyze
{
"analyzer":"stop",
"text":"It is a tiger"
}
POST /_analyze
{
"analyzer":"whitespace",
"text":"I am Iron Man"
}
POST /_analyze
{
"analyzer":"keyword",
"text":"I am Iron Man"
}
这些内置的分词器对于英文文本有很好的支持,但是对于中文却无法进行较好的分析,如下图,在使用默认的分词器进行分词分析时,一句完整的句子将被分割成一个一个单独的中文字符,这显然不符合中文的语言习惯。
因此,对于中文,我们需要使用 ik 分词器进行分析。
ik 分词器的安装和使用
首先在 ik 分词器的 github 网站上选择与 ES 相同版本的 ik 分词器进行下载,将下载后的 zip 文件在文件夹中进行解压。
mkdir elasticsearch_ik
cd elasticsearch_ik
unzip elasticsearch-analysis-ik-7.17.7
解压完成后将解压后的文件夹复制到 docker 容器当中
docker cp elasticsearch_ik elasticsearch:/usr/share/elasticsearch/plugins/
重启 elasticresearch 容器
docker restart elasticresearch
至此 ik 分词器安装成功,可以进行简单的测试,查看 ik 分词器对中文的分词效果,可以看到,ik 分词器将中文语句按照中文词语进行了分词
ik 分词器在其 config 文件夹下的 main.dic 文件中维护了一个字典词库,如果我们需要添加自定义的词库,直接将相应的词语添加到这个文件中即可
Elasticsearch 基本使用
下述操作基于 Kiibana 的 dev_tools 实现,es 与 kibana 的版本均为 7.17.7
索引操作
创建索引:创建一个 2 分本 2 分片的、名称为 test 的索引
PUT /test
{
"settings": {
"number_of_shards": "2",
"number_of_replicas": "2"
}
}
修改索引副本数:将副本数修改为 1(索引的分片不允许修改)
PUT test/_settings
{
"number_of_replicas" : "1"
}
查询索引
GET /test
删除索引
DELETE /test
数据的增删改查
新增数据:指定 id 插入数据
POST /test/_doc/1
{
"name":"曹操",
"country":"魏",
"age":62
}
查询数据
# 查询数据(全局搜索查询)
GET /test/_search
# 查询数据(指定id查询)
GET /test/_doc/1
# 查询数据(按照关键字搜索)
GET /test/_search?q=name:"曹操"
修改数据:ES 中的数据是无法修改的,每一次修改都是对原有数据的覆盖数据的修改分为全局更新和局部更新
修改数据–全局更新:对数据内容进行全部的替换,即使内容相同也执行替换,执行全局更新会使查询时查到的_version
字段 +1
PUT /test/_doc/1
{
"name":"曹操",
"country":"汉"
"age":18
}
修改数据–局部更新:对不同的数据内容进行替换,内容相同的数据不做操作,执行局部更新同样会使查询时查到的_version
字段 +1
POST /test/_update/1
{
"doc":
{
"country":"魏"
}
}
删除数据
DELETE /test/_doc/1
DSL 查询
term
查询:用于查询精确匹配的值,如数字、日期、布尔值等,若需要对匹配值进行整词查询,则需要使用keyword
关键字
POST /test/_search
{
"query": {
"term": {
"age": 18
}
}
}
POST /test/_search
{
"query": {
"term": {
"name.keyword": "曹操"
}
}
}
terms
查询:同term
查询,可以匹配多个值
POST /test/_search
{
"query": {
"terms": {
"age": [18,28]
}
}
}
range
查询:用于范围查询数据,范围查询条件有gt\gte\lt\lte
POST /test/_search
{
"query": {
"range": {
"age": {
"gt": 30,
"lt": 60
}
}
}
}
exists
查询:用于查询包含某个字段的数据
POST /test/_search
{
"query": {
"exists": {
"field": "name"
}
}
}
match
查询:用于标准查询,该查询会进行分词查询
POST /test/_search
{
"query": {
"match": {
"name": "曹操"
}
}
}
match_phrase
查询:该查询不会忽略空格(match
会忽略空格)
POST /test/_search
{
"query": {
"match_phrase": {
"name": "曹操"
}
}
}
bool
查询:可以对多个查询条件进行组合查询,常用的关键字包括:
-
must
:多个查询条件必须完全匹配; -
must_not
:多个查询条件必须完全不匹配; -
should
:多个查询条件至少匹配其中一个;
POST /test/_search
{
"query": {
"bool": {
"must": {
"term": {
"name": "曹"
}
},
"must_not": {
"term": {
"country": "吴"
}
},
"should": [
{
"term": {
"age": 18
}
},
{
"term": {
"age": 28
}
}
]
}
}
}
filter
查询:通常跟bool
连用,用于过滤查询的数据
POST /test/_search
{
"query": {
"bool": {
"filter": {
"term": {
"country": "魏"
}
}
}
}
}
聚合查询
聚合函数查询:max\min\sum\avg
,按照函数意义进行聚合查询
POST /test/_search
{
"aggs": {
"test": {
"min": {
"field": "age"
}
}
},
"size": 0
}
去重查询:cardinality
根据指定字段进行去重统计
POST /test/_search
{
"aggs": {
"test": {
"cardinality": {
"field": "age"
}
}
},
"size": 0
}
统计数量:value_count
根据指定字段进行数据量统计
POST /test/_search
{
"aggs": {
"test": {
"value_count": {
"field": "age"
}
}
},
"size": 0
}
terms 词聚合:使用terms
按照指定字段进行数据分组聚合
POST /test/_search
{
"aggs": {
"test": {
"terms": {
"field": "age"
}
}
},
"size": 0
}
top_hits 聚合:使用top_hits
可以查询按指定字段分组后的前 n 条数据
POST /test/_search
{
"aggs": {
"test": {
"terms": {
"field": "age"
},
"aggs": {
"count": {
"top_hits": {
"size": 3
}
}
}
}
},
"size": 0
}
range 范围聚合:使用range
可以对按照指定字段分组后的数据进行范围分组
POST /test/_search
{
"aggs": {
"group_by_id": {
"range": {
"field": "age",
"ranges": [
{
"from": 20,
"to": 30
},
{
"from": 50,
"to": 60
},
{
"from": 10,
"to": 20
}
]
}
}
},
"size": 0
}
批量操作
批量插入数据
POST _bulk
{ "create" : { "_index" : "test", "_id" : "1" } }
{"name":"曹操","country": "魏","age": 18}
{ "create" : { "_index" : "test", "_id" : "2" } }
{"name":"刘备","country": "蜀","age": 38}
{ "create" : { "_index" : "test", "_id" : "3" } }
{"name":"孙权","country": "吴","age": 28}
{ "create" : { "_index" : "test", "_id" : "4" } }
{"name":"张辽","country": "魏","age": 18}
{ "create" : { "_index" : "test", "_id" : "5" } }
{"name":"张郃","country": "魏","age": 18}
{ "create" : { "_index" : "test", "_id" : "6" } }
{"name":"徐晃","country": "魏","age": 28}
{ "create" : { "_index" : "test", "_id" : "7" } }
{"name":"于禁","country": "魏","age": 38}
{ "create" : { "_index" : "test", "_id" : "8" } }
{"name":"乐进","country": "魏","age": 18}
批量查询数据
POST /test/_mget
{
"ids": [
"4",
"5",
"6"
]
}
批量修改数据
POST _bulk
{ "update" : {"_id" : "4", "_index" : "test"} }
{ "doc" : {"name" : "荀彧"}}
{ "update" : {"_id" : "5", "_index" : "test"} }
{ "doc" : {"name" : "荀攸"}}
批量删除数据
POST _bulk
{ "delete" : { "_index" : "test", "_id" : "4" } }
{ "delete" : { "_index" : "test", "_id" : "5" } }