ElasticSearch01
ES
简介
- 一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能
ELK技术栈组成
- elasticsearch(核心): 负责数据搜索,分析,存储
- kibana: 负责数据可视化
- logstash,beats: 负责数据抓取
Lucene
- ES的底层实现,Apache的开源搜索引擎类库,提供了搜索引擎的核心API
概念
-
正向索引
- 如mysql数据库表中的id就是正向索引,根据id查询数据会非常快,假设表中有一name字段,若根据name字段进行模糊匹配,则不论name字段是否添加了索引,都需要进行全表扫描,将所有name字段满足要求的数据添加到结果集中去
-
倒排索引
-
倒排索引中的重要概念:
-
文档
- 被搜索的数据,每一条数据便是一个文档
-
词条
- 对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条
-
-
创建倒排索引的流程
- 将每一个文档的数据利用算法分词,得到一个个词条
- 创建表,每行数据包括词条、词条所在文档id、位置等信息
- 因为词条唯一性,可以给词条创建索引
-
倒排索引查询流程
- 首先将用户搜索的数据进行分词,得到一个个词条
- 根据词条在倒排索引中查找,得到文档id
- 根据文档id在正向索引中查询文档
-
-
字段
- 每个文档都会包含很多字段,相当于数据库表的列
-
index索引
- 相同类型文档的集合
-
mapping映射
- 索引中文档的字段约束信息,类似数据库中表的结构约束
mysql和elasticsearch的概念对比
MySQL | Elasticsearch | 说明 |
---|---|---|
Table | Index | 索引(index),就是文档的集合,类似数据库的表(table) |
Row | Document | 文档(Document),就是一条条的数据,类似数据库中的行(Row),文档都是JSON格式 |
Column | Field | 字段(Field),就是JSON文档中的字段,类似数据库中的列(Column) |
Schema | Mapping | Mapping(映射)是索引中文档的约束,例如字段类型约束。类似数据库的表结构(Schema) |
SQL | DSL | DSL是elasticsearch提供的JSON风格的请求语句,用来操作elasticsearch,实现CRUD |
DSL请求语句
使用DSL语句对elasticsearch进行操作
# 查询所有数据
GET _search
{
"query": {
"match_all": {}
}
}
# 模拟请求 http://192.168.204.128:9200/
# 不需要路径,使用/
# 不需要DSL
GET /
# 测试分词器,默认的分词器对中文分词基本没用,standard,english,chinese
POST /_analyze
{
"analyzer": "standard",
"text": ["学习java做程序员实在是泰库辣"]
}
# 测试ik分词器,ik_smart: 最少切分(粗粒度),ik_max_word: 最细切分(细粒度)
POST /_analyze
{
"analyzer": "ik_smart",
"text": "学习java做程序员实在是泰库辣"
}
索引库操作
mapping映射属性
-
type:字段数组类型
- 字符串:text(可分词的文本,一般与分词器配合使用),keyword(精确值,不可分词)
- 数值:integer,byte,long,float,double,short
- 布尔boolean
- 日期date
- 对象object
-
index:是否创建索引,默认为true
-
analyzer:分词器
-
properties:子字段
创建索引库和映射
-
基本语法:
- 请求方式:PUT
- 请求路径:/索引库名,可以自定义
- 请求参数:mapping映射
eg:
# 创建索引库 PUT /shifan { "mappings": { "properties": { "info": { "type": "text", "analyzer": "ik_smart" }, "email": { "type": "keyword", "index": false }, "name": { "type": "object", "properties": { "firstName": { "type": "keyword" }, "lastName": { "type": "keyword" } } } } } }
查询索引库
-
基本语法
-
- 请求方式:GET
-
- 请求路径:/索引库名
-
- 请求参数:无
eg:
#查询索引库 GET /shifan
-
修改索引库
-
索引库一旦创建,无法修改mapping。但是允许添加新的字段到mapping中
-
基本语法
-
- 请求方式:PUT
-
- 请求路径:/索引库名/_mapping
-
- 请求参数:properties新字段
eg:
# 添加新的新的字段到索引库中 PUT /shifan/_mapping { "properties":{ "age":{ "type":"integer" } } }
-
删除索引库
-
基本语法
-
- 请求方式:DELETE
-
- 请求路径:/索引库名
-
- 请求参数:无
eg:
# 删除索引库 DELETE /shifan
-
文档操作
新增文档
# 插入文档
POST /shifan/_doc/1
{
"info":"时帆测试数据1",
"email":"aaa@bbb.com",
"name":{
"firstName":"四",
"lastName":"李"
}
}
查询文档
# 查询文档
GET /shifan/_doc/1
删除文档
# 删除文档
DELETE /shifan/_doc/1
修改文档
- 全量修改:先删除原有文档,再插入新的文档
被修改的文档不存在时只做插入操作
# 修改文档
# 全量修改,实际操作:删除原有文档,创建相同文档id的文档插入,若被修改文档id不存在,则直接做插入操作
PUT /shifan/_doc/1
{
"info":"时帆测试数据修改",
"email":"aaa@bbb.cn",
"name":{
"firstName":"三",
"lastName":"张"
}
}
- 增量修改: 只修改指定字段
# 增量修改
POST /shifan/_update/1
{
"doc": {
"email":"123@aaa.com"
}
}
- 个人测试
# 字段不存在,自动创建该字段,并插入
PUT /shifan/_doc/1
{
"age":"时帆测试数据修改222"
}
# 修改不存在的字段会自动在索引库中创建该字段
POST /shifan/_update/1
{
"doc": {
"gender":"男"
}
}
# 批量查询文档
GET /hotel/_search
RestAPI
特殊映射字段
-
地理坐标
- geo_point: 由精度和纬度确定的一个点
- geo_shape: 由多个geo_point组成的复杂几何图形,如两个geo_point组成一条直线
- eg:
"location":{ "type":"geo_point" }
-
组合字段
-
使用copy_to属性将多个字段合并到一起
-
eg:
"all":{ "type":"text", "analyzer":"ik_max_word" }, "name":{ "type":"keyword", "copy_to":"all" }, "brand":{ "type":"keyword", "copy_to":"all" },......
-
初始化RestClient
-
- 引入依赖
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
- 2.覆盖springboot默认的ES版本(默认是7.6.2)
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
-
- 初始化RestHighLevelClient
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://192.168.150.101:9200")
));
RestClient操作索引库
-
创建索引库
-
- 创建Request对象
CreateIndexRequest request = new CreateIndexRequest(“indexName”);
-
- 准备请求参数,即DSL语句
request.source(MAPPING_TEMPLATE, XContentType.JSON);
-
MAPPING_TEMPLATE是定义在常量中的DSL语句
-
- 发送请求
client.indicies().create(request,RequestOptions.DEFAULT)
-
删除索引库
-
- 创建Request对象
DeleteIndexRequest request = new DeleteIndexRequest(“indexName”);
-
- 发送请求
client.indicies().delete(request,RequestOptions.DEFAULT)
-
-
判断索引库是否存在
-
- 创建Request对象
GetIndexRequest request = new GetIndexRequest(“indexName”);
-
- 发送请求
boolean exists =
client.indicies().exists(request,RequestOptions.DEFAULT)
-
RestClient操作文档
-
新增文档
-
- 创建请求对象
IndexRequest request = new IndexRequest(“indexName”).id(“id”);
-
- 准备json数据
request.source(json,XContentType.JSON);
json为json数据,一般为对象转换而来
-
-
- 发送请求
-
client.index(request,RequestOptions.DEFAULT);
-
查询文档
-
- 创建请求对象
GetRequest request = new GetRequest(“indexName”,“id”);
-
- 发送请求
GetResponse response = client.get(request,RequestOptions.DEFAULT);
-
- 解析结果
String json = response.getSourceAsString()
-
-
删除文档
-
- 创建请求对象
DeleteRequest request = new DeleteRequest(“indexName”,“id”);
-
- 发送请求
client.delete(request,RequestOptions.DEFAULT);
-
-
修改文档
-
全量修改
- 与新增文档API完全一致,区别仅在于文档id若存在就做修改,不存在就做新增
-
增量修改
-
- 创建请求对象
UpdateRequest request = new UpdateRequest(“indexName”,“id”);
-
- 准备参数
每两个参数一组构成键值对
request.doc(“age”,“18”,“name”,“shifan”);
-
-
-
发送请求
client.update(request,RequestOptions.DEFAULT);
-
-
-
批量导入文档
-
- 创建请求
BulkRequest request = new BulkRequest();
-
- 准备参数
-
BulkRequest本质上就是请求的集合
request.add(new IndexRequest(“indexName”).id(“101”).source(“json source”,XContentType.JSON));
request.add(new IndexRequest(“indexName”).id(“102”).source(“json source”,XContentType.JSON));
-
- 发送请求
client.bulk(request,RequestOptions.DEFAULT);