ElasticSearch
为什么要学elasticsearch?
SQL:like模糊查询,如果是大数据,就非常慢,索引
Elaticsearch:搜索
ElasticSearch安装
1.熟悉目录
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-46b5cuET-1692867106209)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823111215701.png)]
bin 启动文件
config 配置文件
log4j2 日志配置文件
jvm.options java虚拟机相关的配置
elasticsearch 配置文件 默认9200端口 跨域
lib 相关jar包
modules 功能模块
plugin 插件 ik
2.启动
elasticsearch.bat
访问9200
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ghReGVL5-1692867106209)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823111832552.png)]
3.es-head
npm install
npm run start
默认端口9100
连接测试时发现,端口存在跨域问题,配置es.yml
#配置跨域 开启跨域
http.cors.enabled: true
#全部人都可以访问
http.cors.allow-origin: "*"
重启es服务器,测试连接成功
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-131KyRPP-1692867106210)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823131241469.png)]
4安装kabana
版本必须和es一致,是一个标准的前端工程
解压
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6Bxp9LHq-1692867106210)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823132604652.png)]
启动
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r69HfLyq-1692867106210)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823132856145.png)]
访问测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kza8M89s-1692867106210)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823132916403.png)]
开发工具
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ELURvCK-1692867106211)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823133206263.png)]
修改配置,设置中文
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Li1bP2s0-1692867106211)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823133416884.png)]
ES核心概念
集群,节点,索引,类型,文档,分片,映射是什么?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MntXvafY-1692867106212)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823142241728.png)]
1.索引
2.字段类型(mapping)
3.文档(documents)
4.分片(倒排索引)
IK分词器
分词:把一段中文或者别的划分成为一个个的关键字,我们在搜索的时候会把自己的信息进行分词,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词器是将每一个字看成一个词,这显然是不符合要求的,所以需要使用ik分词器来解决这个问题
ik提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9BEXlv4-1692867106212)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823143025061.png)]
- 解压 安装ik分词器,重启es服务
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JwJe4qMC-1692867106213)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823143146059.png)]
-
可以看到ik插件被加载了
-
使用kibana进行测试
-
查看不同的分词器效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWRM5gWi-1692867106214)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823143856860.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k2sJFTcC-1692867106214)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823143907749.png)]
ik_max_word为最细粒度划分,穷尽词库的可能
ik_smart 最小粒度划分,不可能有重复的字
自己需要的词,需要自己加到分词器的字典中
- ik分词器增加自己的配置
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ECJkcwPX-1692867106214)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823144409450.png)]
- 重启es
以后需要自己配置分词,直接在配置文件中配置词典即可
Rest风格说明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ovAsGkXn-1692867106214)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823145024418.png)]
- 基础测试
关于索引的基本操作
1.创建一个索引
PUT /test1/type1/1
{
"name": "芜湖",
"age": 3
}
#格式:
PUT/索引名/类型名/文档id
{请求体}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RSu1euRY-1692867106215)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823145957365.png)]
完成了自动增加索引
数据类型
- 字符串类型
text,keyword关键字 - 数值类型
long,integer,short,byte,double,float,half float,scaled float - 日期类型
date - 布尔值类型
boolean - 二进制类型
binary - 等等…
2.指定字段的类型 创建索引规则
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-btIWcWF9-1692867106215)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823151115399.png)]
3.获得规则
可以通过get请求获得具体的信息
GET test2
4.查看默认的信息
PUT /test3/_doc/1
{
"name": "wuhu",
"age": "13",
"birthday":"1997-01-05"
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B1ZnZ5dk-1692867106215)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823151504359.png)]
如果主机的文档字段没有指定,那么es就会给我们默认配置字段类型
5.修改索引
- 提交还是put,然后覆盖
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KAj2xjri-1692867106216)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823152121738.png)]
修改后版本会增加,状态updated
- 使用post进行更新
POST /test3/_doc/1
{
"doc":{
"name":"大司马"
}
}
6.删除索引
DELETE test3
关于文档的基本操作(重点)
基本操作
1.添加一条文档
PUT /wuhu/user/1
{
"name":"卢本伟",
"age": 23,
"desc": "我tm真没开挂",
"tags": ["开挂","斗地主","慈善"]
}
#返回结果
{
"_index" : "wuhu",
"_type" : "user",
"_id" : "2",
"_version" : 1,
"result" : "created", #表示创建
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
2.获取数据
最简单的搜索
GET wuhu/user/1
3.更新数据
- 使用PUT更新 PUT如果不传递值,会被覆盖
PUT wuhu/user/3
{
"name":"蔡徐坤666",
"age": 22,
"desc": "坤坤",
"tags": ["鸡你太美","rap","篮球"]
}
更新之后,version会加1,代表这条数据被改动的次数,result会变成updated
- 使用POST _update,推荐使用这种更新方式,只需写你想改的属性
POST wuhu/user/1/_update
{
"doc":{
"desc": "我开挂了"
}
}
4.简单的搜索
最简单的搜索
GET wuhu/user/1
简单的条件查询-精确匹配
GET wuhu/user/_search?q=name:卢本伟
5.复杂操作搜索select(排序,分页,高亮,模糊查询,精准查询)
要查询的对象+查询的参数体json对象
- 条件查询
GET wuhu/user/_search
{
"query": {
"match": {
"name": "蔡" #按照参数进行查询
}
},
"sort": [ #排序功能
{
"age": { #通过哪个字段进行排序
"order": "desc" #升序/降序
}
}
],
"from": 0, #分页查询,从第几个开始查询
"size": 1, #查几个
"_source": ["name","desc"] #结果的过滤
}
查询得到的结果:
hits:索引和文档的信息
查询结果的总数
具体的文档
匹配的分数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V2Ik6Ck9-1692867106216)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823160437382.png)]
- 布尔值查询
GET wuhu/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "蔡徐坤"
}
},
{
"match": {
"age": "25"
}
}
]
}
}
}
must(and):所有的条件都要符合
should(or):符合其中一个条件即可
must_not(not)反向操作
filter过滤器 可以使用filter进行数据的过滤
- gt大于
- gte大于等于
- lt小于
- lte小于等于
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xHfs18D5-1692867106216)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823162451482.png)]
可以使用多个条件进行过滤
-
匹配多个搜索条件 多个查询条件之间用空格隔开
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mLOEWeR3-1692867106216)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823163143939.png)]
-
精确查询
term查询是直接通过倒排索引指定的词条进度进行精确查找的
term:直接查询精确的(效率更高)
match:会使用分词器解析(先分析文档,然后再通过分析的文档进行查询)
-
多个值匹配查询 精确查询多个值
GET testdb/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"t1": "22"
}
},
{
"term": {
"t1": "32"
}
}
]
}
}
}
- 高亮查询
GET wuhu/user/_search
{
"query": {
"match": {
"name": "蔡徐"
}
},
"highlight": { #设置高亮
"pre_tags": "<p class='key' style='color:red'>", #自定义高亮条件
"post_tags": "<p>",
"fields": {
"name":{}
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9cIqshGf-1692867106217)(C:\Users\19627\AppData\Roaming\Typora\typora-user-images\image-20230823170745030.png)]
集成SpringBoot
1.导入依赖
<!--高级别es-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
2.修改版本号,与本地es保持一致
<!--自定义es版本依赖,保证和本地一致-->
<elasticsearch.version>7.6.2</elasticsearch.version>
3.设置es配置类
@Configuration
public class ElasticSearchClientConfig {
//xml
@Bean
RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost",9200,"http")));
return client;
}
}
或者在yml配置文件中配置
elasticsearch:
uris: http://localhost:9200
4.编写测试类 具体的api测试
创建索引
@SpringBootTest
public class ESTest {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
//索引的创建 Request
@Test
void testCreate() throws IOException {
//1.创建索引的请求
CreateIndexRequest request = new CreateIndexRequest("wuhu_index");
//2.执行请求,请求后获得响应
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
}
//测试获取索引
@Test
void testExistsIndex() throws IOException{
GetIndexRequest request = new GetIndexRequest("wuhu_index");
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//测试删除索引
@Test
void testExitsIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("wuhu_index");
//删除
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
文档测试
//测试添加文档
@Test
void testAddDocument() throws IOException {
//创建对象
User user = new User("金轮",22);
//创建请求
IndexRequest request = new IndexRequest("wuhu_index");
//规则 put /wuhu_index/_doc/1
request.id("1");
//request.timeout(TimeValue.timeValueSeconds(1));
request.timeout("1s");
//将数据放入请求 json
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求
IndexResponse index = client.index(request, RequestOptions.DEFAULT);
System.out.println(index.toString());
System.out.println(index.status());//对应我们命令返回的状态 CREATED
}
//测试获取文档
@Test
void testIsExists() throws IOException {
GetRequest index = new GetRequest("wuhu_index","1");
//不获取返回的_source的上下文
index.fetchSourceContext(new FetchSourceContext(false));
index.storedFields("_none_");
boolean exists = client.exists(index, RequestOptions.DEFAULT);
System.out.println(exists);
}
//获取文档信息
@Test
void testGetDocument() throws IOException {
GetRequest index = new GetRequest("wuhu_index","1");
GetResponse response = client.get(index, RequestOptions.DEFAULT);
System.out.println(response.getSourceAsString());//打印文档的内容
System.out.println(response);
}
//更新文档记录
@Test
void testUpdateDocument() throws IOException {
//获得更新请求
UpdateRequest request = new UpdateRequest("wuhu_index", "1");
//封装请求
request.timeout("1s");
User user = new User("卢本伟", 22);
//把对象封装成json放入请求中
request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
System.out.println(update.status());
}
//删除文档记录
@Test
void testDeleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("wuhu_index", "1");
request.timeout("1s");
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
System.out.println(delete.status());
}
批处理请求
//大批量的插入和查询
@Test
void testBulkRequest() throws IOException{
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.timeout("10s");
List<User> users = new ArrayList<>();
users.add(new User("wuhu",22));
users.add(new User("niubi",32));
users.add(new User("haha",24));
users.add(new User("mabi",25));
//批处理请求
for (int i = 0; i < users.size(); i++) {
//批量更新和批量删除就在这里请求
bulkRequest.add(new IndexRequest("wuhu_index").id(""+(i+1)).source(JSON.toJSONString(users.get(i)),XContentType.JSON));
}
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulkResponse.hasFailures()); //false代表没有失败 成功了
}
搜索
//查询
//搜索请求
//条件构造
@Test
void testSearch() throws IOException {
//创建请求
SearchRequest searchRequest = new SearchRequest("wuhu_index");
//构建搜索的条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//设置查询条件 使用QueryBuilders工具类快速匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "wuhu");
sourceBuilder.query(termQueryBuilder);
//构建分页
//sourceBuilder.from();
//sourceBuilder.size();
//构建查询时间
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(search.status());
//遍历打印
for (SearchHit hit : search.getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
实战
爬虫
前后端分离
SearchSourceBuilder();
//设置查询条件 使用QueryBuilders工具类快速匹配
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "wuhu");
sourceBuilder.query(termQueryBuilder);
//构建分页
//sourceBuilder.from();
//sourceBuilder.size();
//构建查询时间
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(search.status());
//遍历打印
for (SearchHit hit : search.getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
### 实战
#### 爬虫
#### 前后端分离
#### 搜索高亮