ElasticSearch 学习
ElasticSearch 学习
1. 下载安装 ElasticSearch相关环境
下载ElasticSearch https://www.elastic.co/cn/downloads/elasticsearch
下载Kibana https://www.elastic.co/cn/downloads/kibana
2. 安装运行
如果是Windows上面的
直接解压ElasticSearch压缩包,点击 bin目录下的 elasticsearch.bat
运行
浏览器访问 127.0.0.1:9200
得到如下回显信息
1 | { |
安装ElasticSearch 网页界面
下载 elasticsearch-head https://github.com/mobz/elasticsearch-head
因为是个 前端框架包 ,需要配置node.js https://nodejs.org/en/
安装完 node.js后,配置 淘宝镜像 :
1 | npm install -g cnpm --registry=https://registry.npm.taobao.org |
配置启动:
1 | cnpm install # 添加相关依赖 |
访问http://localhost:9100/
得到如下界面
因为ElasticSearch默认不允许跨域使得 elasticsearch-head 能访问到,这里需要配置elasticsearch的跨域访问配置,在ElasticSearch的解压包 目录下的 config 文件夹下的 elasticsearch.yml 添加如下配置:
1 | http.cors.enabled: true |
重新访问得到的界面如下:
3. 安装 Kibana
如果是Windows上面的
直接解压Kibana压缩包,点击 bin目录下的 kibana.bat
运行
浏览器访问 127.0.0.1:5601
得到如下回显信息
汉化
修改解压Kibana解压文件下 config/kibana.yml
1 | # 找到这处注释 |
4. ElasticSearch 概述
- 索引
- 字段类型(mapping)
- 文档(document)
ElasticSearch是面向文档的,ElasticSearch中 一切都是JSON
ElasticSearch 和 传统的 关系型数据库对比
Mysql | ElasticSearch |
---|---|
数据库(database) | 索引(indices) |
表(tables) | type(慢慢会被弃用) |
行(rows) | 文档(document) |
字段(columns) | fields |
5. ElasticSearch 使用 ik分词器
下载 https://github.com/medcl/elasticsearch-analysis-ik/releases
下载后 解压到 elasticsearch的 plugins 目录下,设置文件夹名为 ik,如下:
重启ElasticSearch,可看见 控制台 加载了 ik
也可在 ElasticSearch 的 bin 目录下使用 cmd 控制台 输入如下命令查看插件信息
1 | elasticsearch-plugin |
使用 Kibana 测试 ik
1 | # 在开发者工具中输入 如下命令 ik_smart 表示 对字段的 最小切分 |
如果某些 字段被拆开了,即自己需要的词,需要把这个字段加到分词器的字典中
ik 分词器 增加自己的配置
重启 es
一般都能够实现字段分词设置
Rest 风格说明
Method | url地址 | 描述 |
---|---|---|
PUT | location:9200/索引名称/类型名称/文档id | 创建文档(指定文档id) |
POST | location:9200/索引名称/类型名称 | 创建文档(随机文档id) |
POST | location:9200/索引名称/类型名称/文档id/_update | 修改文档 |
DELETE | location:9200/索引名称/类型名称/文档id | 删除文档 |
GET | location:9200/索引名称/类型名称/文档id | 查询文档通过文档id |
POST | location:9200/索引名称/类型名称/_search | 查询所有数据 |
基础测试
创建一个索引
1
2
3
4PUT /索引名/类型名/文档id
{
请求体
}ElasticSearch 的基本数据类型
指定字段的类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24输入如下命令
PUT /test2
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"age":{
"type": "long"
},
"birthday":{
"type": "date"
}
}
}
}
得到如下回显
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "test2"
}获取这个规则信息
1
GET 索引名称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35输入
GET test2
得到如下信息
{
"test2" : {
"aliases" : { },
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"birthday" : {
"type" : "date"
},
"name" : {
"type" : "text"
}
}
},
"settings" : {
"index" : {
"creation_date" : "1594005434518",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "PRZ3KvJ-TrGCqSLWe5dMhw",
"version" : {
"created" : "7060299"
},
"provided_name" : "test2"
}
}
}
}查看ElasticSearch的状态信息
1
2
3GET _cat/health
GET _cat/indices?v修改索引文档信息
可以直接使用 PUT命令重复提交数据,但是之前PUT的值必须在这次请求中
使用
POST /索引名/类型/文档id/_update
修改1
2
3
4
5
6POST /索引名/类型/文档id/_update
{
"doc":{
请求体
}
}删除索引
1
DELETE 索引名
基于文档的 基本操作
简单操作
添加 PUT
1
2
3
4PUT /索引名/类型/文档id
{
请求体
}更新
PUT
1
2
3
4PUT /索引名/类型/文档id
{
请求体 # 该请求体里面的值必须全部传入,否则之前添加的值会被设置为空
}POST
1
2
3
4
5
6POST /索引名/类型/文档id
{
"doc":{
请求体
}
}
查询 GET
获取某文档
1
GET /索引名/类型/文档id
在索引中进行查询
1
GET /索引名/类型/_search?q=属性:值 # 这里的值可以是某属性值的部分字段
删除 DELETE
1
DELETE /索引名/类型/文档id
复杂搜索
1 | 模糊匹配某值 但是这种查询不支持多个查询条件 |
过滤器 filter gte 表示 大于等于 e:等于 ,lte 类似
1 | GET /jiang/user/_search |
匹配多个条件
1 | 多个条件使用空格隔开,只要满足其中一个结果就可以被查出,这个时候可以通过分值基础的判断 |
精确查询
term 查询是直接通过倒排索引指定的词条进行精确的查找
关于分词:
term 直接查询精确的
match 会使用分词器解析(先分析文档,然后通过分析的文档进行查询)
两个类型 text keyword
text
keyword
多个值匹配的精确查询
1 | 添加测试数据 |
高亮查询
搜索的结果会添加HTML标签显示
1 | GET jiang/user/_search |
- 匹配
- 按条件匹配
- 精确匹配
- 区间范围匹配
- 匹配字段过滤
- 多条件查询
- 高亮查询
集成 springboot
创建项目 并导入依赖
1
2
3
4
5
6
7
8
9
10
11<!-- 检查当前 springboot默认导入的包是否和当前环境包一致,如果不一致的话在properties中设置相对应的版本信息 -->
<properties>
<!-- 这里配置和环境版本一致的 -->
<elasticsearch.version>7.6.2</elasticsearch.version>
</properties>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>配置ElasticSearch 连接
1
2
3
4
5
6
7
8
9
10
11
12
public class ElasticSearchClientConfig {
public RestHighLevelClient restHighLevelClient(){
// 配置连接ElasticSearch
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}连接测试
创建索引
1
2
3
4
5
6
7
8
9
10// 创建索引
void testCreatedIndex() throws IOException {
// 1.创建索引请求
CreateIndexRequest request = new CreateIndexRequest("jiang_index");
// 2.执行请求
CreateIndexResponse createIndexResponse =
restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}获取索引
1
2
3
4
5
6
7// 获取索引 判断其是否存在
void testExistIndex() throws IOException {
GetIndexRequest request = new GetIndexRequest("jiang_index");
boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}删除索引
1
2
3
4
5
6
7// 删除索引
void testDeleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("jiang_index");
AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}创建文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21// 测试添加文档
void testAddDocument() throws IOException {
// 创建对象
User user = new User("葛大", 10);
// 创建请求
IndexRequest request = new IndexRequest("jiang_index");
// 规则 put /jiang_index/_doc/1
request.id("1");
request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
// 将数据放入请求中 json格式
request.source(JSON.toJSONString(user), XContentType.JSON);
IndexResponse index = restHighLevelClient.index(request, RequestOptions.DEFAULT);
System.out.println(index.toString());
System.out.println(index.status());
}crud文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115//获取文档 判断是否存在 get /index/doc/1
void testIsExists() throws IOException {
GetRequest request = new GetRequest("jiang_index", "1");
// 不获取返回的 _source 的上下文 (这样效率更高)
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
boolean exists = restHighLevelClient.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
// 获取文档信息
void testGetDocument() throws IOException {
GetRequest request = new GetRequest("jiang_index", "1");
GetResponse response = restHighLevelClient.get(request, RequestOptions.DEFAULT);
// 打印文档的内容
System.out.println(response.getSourceAsString());
//返回的全部内容 和命令 是一样的
System.out.println(response);
}
// 获取文档信息
void testUpdateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("jiang_index", "1");
request.timeout("1s");
User user = new User("葛大的大", 24);
request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse update = restHighLevelClient.update(request, RequestOptions.DEFAULT);
System.out.println(update.status());
System.out.println(update);
}
// 获取文档信息
void testDeleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("jiang_index", "1");
// 设置请求时间
request.timeout("1s");
DeleteResponse delete = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
System.out.println(delete.status());
System.out.println(delete);
}
// 批量插入数据
void testBulkRequest() throws IOException {
BulkRequest request = new BulkRequest();
request.timeout("10s");
ArrayList<User> list = new ArrayList<>();
list.add(new User("葛大", 29));
list.add(new User("赵二", 12));
list.add(new User("张三", 31));
list.add(new User("李四", 33));
list.add(new User("王五", 23));
list.add(new User("陈六", 6));
list.add(new User("潘七", 85));
for (int i = 0; i < list.size(); i++) {
request.add(new IndexRequest("jiang_index")
.source(JSON.toJSONString(list.get(i)), XContentType.JSON));
}
BulkResponse bulkResponse = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
// 是否失败 false 表示 成功
System.out.println(bulkResponse.hasFailures());
System.out.println(bulkResponse);
}
// 查询
/**
* SearchRequest 搜索请求
* HighlightBuilder 构建高亮
* TermQueryBuilder 精确查询
* MatchQueryBuilder 模糊匹配
* xxx QueryBuilders 对应命令
* @throws IOException
*/
void testSearch() throws IOException {
SearchRequest request = new SearchRequest("jiang_index");
// 构建搜索条件
SearchSourceBuilder builder = new SearchSourceBuilder();
// 查询条件 使用 QueryBuilders 工具实现
// QueryBuilders.termQuery 精确匹配
// QueryBuilders.matchAllQuery() 匹配所有
MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", "张三");
builder.query(queryBuilder);
builder.timeout(new TimeValue(60, TimeUnit.SECONDS));
request.source(builder);
SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
System.out.println(JSON.toJSONString(response.getHits()));
System.out.println("================================");
for (SearchHit fields : response.getHits().getHits()) {
System.out.println(fields.getSourceAsMap());
}
}