ElasticSearch 入门到放弃(持续更新中)
文章目录
- 前言
- Ealsticsearch 入门
- 正向索引、倒排索引
- 正向索引
- 倒排索引
- 正向和倒叙对比
- ES数据库基本概念
- 文档和字段
- 索引和映射
- MySQL与ElasticSearch
- ES的安装
- 基于docker
- 基于docker-compose
- 测试安装
- Kibana的安装
- 基于docker
- 基于docker-compose
- IK分词器安装
- IK分词器模式
- ik_smart
- ik_max_word
- 自定义分词库
- IK停词器
- 索引库操作
- Mapping 属性映射
- Index 索引操作
- 创建索引
- 查询索引
- 更新索引
- 删除索引
- Document 文档操作
- 创建文档
- 查询文档
- 删除文档
- 更新文档
前言
什么是ElasticSearch?
一个开源的分布式搜索引擎,可以实现搜索,日志统计,分析,系统监控等
什么是ealstic stack (ELK)?
是以elasticsearch为核心的技术栈,包括beats,Logstash,Kibana,ElasticSearch
Ealsticsearch 入门
正向索引、倒排索引
正向索引
是基于MySQL这样的正向索引而言
设置了索引的话查询很快,但是模糊查询则很慢
如果是根据id查询,那么直接走索引,查询会很快
但是基于title做模糊查询,只能逐行扫描数据,也就是全表扫描,随着数据量的增加,查询效率也会越来越低,当数据量达到百万时,就是一场灾难。
倒排索引
倒排索引中有两个非常重要的概念:
- 文档
Document
:用来搜索的数据,其中每一条数据就是一个文档,例如一个网页,一个商品信息 - 词条
Term
:对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条
创建倒排索引是对正向索引的一种特殊处理,流程如下:
- 将没一个文档的数据利用分词,得到一个个词条
- 创建表,每行数据包括词条,词条所在的文档,位置等信息
- 因为词条唯一性,可以给词条创建索引,例如hash表结构索引
正向和倒叙对比
- 正向索引是最传统的,根据id索引的方式。但根据词条查询时,必须先逐条获取每个文档,然后判断文档中是否包含所需要的词条,是根据文档找词条的过程。
- 而倒排索引则相反,是先找到用户要搜索的词条,根据词条得到保护词条的文档的id,然后根据id获取文档。是根据词条找文档的过程。
正向索引:
- 优点:
- 可以给多个字段创建索引
- 根据索引字段搜索、排序速度非常快
- 缺点:
- 根据非索引字段,或者索引字段中的部分词条查找时,只能全表扫描。
倒排索引:
- 优点:
- 根据词条搜索、模糊搜索时,速度非常快
- 缺点:
- 只能给词条创建索引,而不是字段
- 无法根据字段做排序
ES数据库基本概念
文档和字段
文档类似于数据库中的一条数据,字段就像数据库中列
elasticSearch
是面向文档document存储,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json格式后存储在es中。
而json文档中往往包含很多字段Field,类似于mysql数据库中的列。
索引和映射
索引就像数据库中的表,映射就像数据库表中的表结构
索引(Index),就是相同类型的文档的集合【类似mysql中的表】
例如:
- 所有用户文档,就可以组织在一起,称为用户的索引;
- 所有商品的文档,可以组织在一起,称为商品的索引;
- 所有订单的文档,可以组织在一起,称为订单的索引;
数据库的表会有约束信息,用来定义表的结构、字段的名称、类型等信息。因此,索引库中就有映射(mapping),是索引中文档的字段约束信息,类似表的结构约束。
MySQL与ElasticSearch
MySQL:擅长事务类型的操作,可以确保数据的安全性和一致性。
ElasticSearch:擅长海量的数据的搜索,分析,计算
ES的安装
基于docker
docker run -d \
--name es \
-e "http.host=0.0.0.0"
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
-e "discovery.type=single-node" \
-v /usr/local/docker/es/data:/usr/share/elasticsearch/data \
-v /usr/local/docker/es/logs:/usr/share/elasticsearch/logs \
-v /usr/local/docker/es/plugins:/usr/share/elasticsearch/plugins \
--privileged \
--network app_net \
-p 9200:9200 \
-p 9300:9300 \
elasticsearch:7.14.2
基于docker-compose
cd /usr/local/docker/
mkdir es
cd es
# 创建数据卷宿主机路径
mkdir -p data logs plugins config/analysis-ik
# 授权
chmod 777 data/ logs/ plguins/ config/
version: '3.8'
services:
# elasticsearch
es:
image: docker.elastic.co/elasticsearch/elasticsearch:7.14.2
container_name: es
restart: always
ports:
- "9200:9200"
- "9300:9300"
environment:
- "discovery.type=single-node"
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "http.host=0.0.0.0"
volumes:
- /usr/local/docker/es/data:/usr/share/elasticsearch/data
- /usr/local/docker/es/logs:/usr/share/elasticsearch/logs
- /usr/local/docker/es/plugins:/usr/share/elasticsearch/plugins
- /usr/local/docker/es/config/analysis-ik:/usr/share/elasticsearch/config/analysis-ik
networks:
- app_net
networks:
app_net:
driver: bridge
测试安装
docker ps
查看进程情况
http://ip:9200/
查看服务安装是否成功
Kibana的安装
基于docker
docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601 \
kibana:7.14.2
基于docker-compose
version: '3.8'
services:
# elasticsearch
es:
image: docker.elastic.co/elasticsearch/elasticsearch:7.14.2
container_name: es
restart: always
ports:
- "9200:9200"
- "9300:9300"
environment:
- "discovery.type=single-node"
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "http.host=0.0.0.0"
volumes:
- /usr/local/docker/es/data:/usr/share/elasticsearch/data
- /usr/local/docker/es/logs:/usr/share/elasticsearch/logs
- /usr/local/docker/es/plugins:/usr/share/elasticsearch/plugins
networks:
- app_net
# kibana
kibana:
image: docker.elastic.co/kibana/kibana:7.14.2
container_name: kibana
restart: always
ports:
- "5601:5601"
environment:
- "ELASTICSEARCH_HOSTS=http://es:9200"
networks:
- app_net
networks:
app_net:
driver: bridge
IK分词器安装
# 进入容器内部
docker exec -it es bash
# 执行安装命令
./bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/7.14.2
# 退出容器内部
exit
# docker-compose 重启es
docker-compose restart es
# docker 重启es
docker restart es
IK分词器模式
ik_smart
智慧拆分,最少切分
ik_max_word
最细切分
自定义分词库
cd /usr/local/docker/es/config/analysis-ik/
# 创建自定义的分词库文件
touch ext.dic
# 追加自己的分词
你打我撒
巴适得板
....
# 更新分词器配置
vim IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
# 重启es
docker-compose restart es
IK停词器
# 向stopword.dic文件追加停词器
的
是
啊
阿
在
...
# 更新分词器配置
vim IKAnalyzer.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict">ext.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords">stopword.dic</entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
# 重启es
docker-compose restart es
预期满足!“的”,“啊”是跳过分词的。
索引库操作
Mapping 属性映射
Index
索引库就类似数据库表,mappnig
映射就类似表的结构。
mapping 是对索引库中文档结构的约束
**type**
:字段数据类型,常见的类型有:- 字符串:
text
(可分词文本),keyword
(精确值,例如:品牌,国家,ip地址等) - 数值:
long
,Integer
,short
,byte
,double
,float
- 布尔:
boolean
- 日期:
date
- 对象:
object
- 地图:
geo_point
由经纬度确定的一个点。例如:“32.8752345,120.2981576” - 坐标:
geo_shape
由多个geo_point组成的复杂几何图形,例如一条直线:“LINESTRING(-77.036553 388.897676,-77.009051 38.889939)”
- 字符串:
- index:是否创建索引,默认true
- analyzer:使用分词器类型
- properties:字段的子字段
Index 索引操作
简单的CRUD
- 创建索引:PUT /索引名
- 查询索引:GET /索引名
- 删除索引:DELETE /索引名
- 修改索引库(添加字段):PUT /索引名/_mapping
创建索引
PUT /user
{
"mappings": {
"properties": {
"userId":{
"type": "long"
},
"username":{
"type": "text",
"analyzer": "ik_smart"
},
"profile":{
"type": "keyword",
"index": false
},
"age":{
"type": "integer",
"index": false
},
"address":{
"properties": {
"city":{
"type":"keyword",
"index":false
},
"area":{
"type":"keyword",
"index":false
}
}
}
}
}
}
查询索引
GET /user
#! Elasticsearch built-in security features are not enabled. Without authentication, your cluster could be accessible to anyone. See https://www.elastic.co/guide/en/elasticsearch/reference/7.14/security-minimal-setup.html to enable security.
{
"user" : {
"aliases" : { },
"mappings" : {
"properties" : {
"address" : {
"properties" : {
"area" : {
"type" : "keyword",
"index" : false
},
"city" : {
"type" : "keyword",
"index" : false
}
}
},
"age" : {
"type" : "integer",
"index" : false
},
"doc" : {
"properties" : {
"email" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"email" : {
"type" : "text",
"analyzer" : "ik_smart"
},
"profile" : {
"type" : "keyword",
"index" : false
},
"userId" : {
"type" : "long"
},
"username" : {
"type" : "text",
"analyzer" : "ik_smart"
}
}
},
"settings" : {
"index" : {
"routing" : {
"allocation" : {
"include" : {
"_tier_preference" : "data_content"
}
}
},
"number_of_shards" : "1",
"provided_name" : "user",
"creation_date" : "1741833092487",
"number_of_replicas" : "1",
"uuid" : "Nw2N6NvtQlysXix9mqfw1A",
"version" : {
"created" : "7140299"
}
}
}
}
}
更新索引
PUT /user/_mapping
{
"properties":{
"email":{
"type":"text",
"analyzer" : "ik_smart"
}
}
}
删除索引
DELETE /user_d
Document 文档操作
简单的CRUD操作
- 创建文档:POST /索引名/_doc/文档id
- 查询文档:
- 查询当前索引下所有文档数据:GET /索引名/_search
- 查询指定文档:GET /索引名/_doc/文档id
- 删除文档:DELETE /索引名/_doc/文档id
- 更新文档:
- 全量更新:PUT /索引名/_doc/文档id (为空的值则会赋值为空)
- 增量更新:POST /索引名/_update/文档id {“doc”:{}} (只会更新doc中的字段)
创建文档
POST /user/_doc/1
{
"userId":1,
"username":"admin",
"profile":"个性签名1111212121",
"age":27,
"address":{
"city":"昆明",
"area":"官渡区"
},
"email":"moon.nie@infocare.org.cn"
}
查询文档
GET /user/_doc/1
GET /user/_doc/2
GET /user/_doc/3
GET /user/_search
删除文档
DELETE /user_d
更新文档
PUT /user/_doc/3
{
"userId":3,
"username":"updateUser11",
"profile":"updateUser11",
"age":117,
"address":{
"city":"昆1明",
"area":"五华1区"
}
}
POST /user/_update/3
{
"doc":{
"email":"nnn111n@163.com"
}
}