EleasticSearch
ELK是什么?
ELK=elasticsearch+Logstash+kibana
elasticsearch:后台分布式存储以及全文检索
logstash: 日志加工、“搬运工”
kibana:数据可视化展示。
ELK架构为数据分布式存储、可视化查询和日志解析创建了一个功能强大的管理链。 三者相互配合,取长补短,共同完成分布式大数据处理工作。
注意 JDk最低1.8
官网下载最新EleasticSearch
区bin目录下双击EleasticSearch.bat启动 9200端口访问Web页面
安装可视化界面
head插件依赖于nodejs
下载node.jshttps://nodejs.org/en/
进入可视化文件head目录执行 npm install
npm install
安装完成之后
http://localhost:9100/ 可视化工具WEB页面
可视化工具访问ES 面临跨域问题 区修改配置文件
Kibana
https://www.elastic.co/cn/kibana
kibana版本要和ES版本一致 否则出错
解压后点击bin下的bat启动
kibana-Request Timeout after 30000ms故障解决
修改配置文件/etc/kibana/kibana.yml,将#去掉,然后将30000毫秒(也就是30s)更改成90000(90秒),这个根据实际情况进行修改。修改完毕后,重启服务
打开5601
ES核心
面向文档 下面是数据库和ES对比
ES一个人就是集群 默认集群名字叫ES
倒排索引
ES使用倒排索引的结构作为底层结构,这种结构适用于全文搜索
Lucene倒排索引原理 Lucene是一个高性能的java全文检索工具包,它使用的是倒排文件索引结构。该结构及相应的生成算法如下: 0)设有两篇文章1和2 文章1的内容为:Tom lives in Guangzhou,I live in Guangzhou too. 文章2的内容为:He once lived in Shanghai. 取得关键词 1)由于lucene是基于关键词索引和查询的,首先我们要取得这两篇文章的关键词,通常我们需要如下处理措施 a.我们现在有的是文章内容,即一个字符串,我们先要找出字符串中的所有单词,即分词。英文单词由于用空格分隔,比较好处理。中文单词间是连在一起的需要特殊的分词处理。 b.文章中的”in”, “once” “too”等词没有什么实际意义,中文中的“的”“是”等字通常也无具体含义,这些不代表概念的词可以过滤掉 c.用户通常希望查“He”时能把含“he”,“HE”的文章也找出来,所以所有单词需要统一大小写。 d.用户通常希望查“live”时能把含“lives”,“lived”的文章也找出来,所以需要把“lives”,“lived”还原成“live” e.文章中的标点符号通常不表示某种概念,也可以过滤掉 在lucene中以上措施由Analyzer类完成 经过上面处理后 文章1的所有关键词为:[tom] [live] [guangzhou] [i] [live] [guangzhou] 文章2的所有关键词为:[he] [live] [shanghai] 建立倒排索引 2) 有了关键词后,我们就可以建立倒排索引了。上面的对应关系是:“文章号”对“文章中所有关键词”。倒排索引把这个关系倒过来,变成:“关键词”对“拥有该关键词的所有文章号”。文章1,2经过倒排后变成 关键词 文章号 guangzhou 1 he 2 i 1 live 1,2 shanghai 2 tom 1 通常仅知道关键词在哪些文章中出现还不够,我们还需要知道关键词在文章中出现次数和出现的位置,通常有两种位置:a)字符位置,即记录该词是文章中第几个字符(优点是关键词亮显时定位快);b)关键词位置,即记录该词是文章中第几个关键词(优点是节约索引空间、词组(phase)查询快),lucene中记录的就是这种位置。 加上“出现频率”和“出现位置”信息后,我们的索引结构变为: 关键词 文章号[出现频率] 出现位置 guangzhou 1[2] 3,6 he 2[1] 1 i 1[1] 4 live 1[2],2[1] 2,5,2 shanghai 2[1] 3 tom 1[1] 1 以live 这行为例我们说明一下该结构:live在文章1中出现了2次,文章2中出现了一次,它的出现位置为“2,5,2”这表示什么呢?我们需要结合文章号和出现频率来分析,文章1中出现了2次,那么“2,5”就表示live在文章1中出现的两个位置,文章2中出现了一次,剩下的“2”就表示live是文章2中第 2个关键字。 以上就是lucene索引结构中最核心的部分。我们注意到关键字是按字符顺序排列的(lucene没有使用B树结构),因此lucene可以用二元搜索算法快速定位关键词。
IK分词器
下载IK分词器 必须和ES版本一致 否则启动时秒退
https://github.com/medcl/elasticsearch-analysis-ik
把解压的目录放道ES的plugins目录下即可
重启所有服务
IK分词器有俩种算法:ik_smart最少切分 ik_max_word 最细力度切分
如果需要特殊指定一些词需要自己指定加入到分词字典中
如何自定义字典?
我们打开分词配置文件点开一个后缀为.dic的文件看
看完之后照猫画虎,那我们自己写一个文件
写完之后如何生效呢?
进入指定文件指定自己写的字典使其生效 改完重启
Restful风格
1建索引并插入数据(相当于建库)
注意 类型不建议使用了 以后键索引不要写类型 默认为_doc
put /索引名/类型/id
{"属性名" "属性值", "" ""}
2建库指定规则 给库中的字段指定类型 不插入数据
3获得规则和数据
GET /索引 就是获取表结构信息
GET /索引/类型/id 就是获取表中的数据
4删除 delete 索引 或delete/索引/id/ 删除数据
5修改 使用post _update
指定修改 某个字段
如果使用put修改 没覆盖的数据会变成空
搜索操作
所有搜索用get
搜索学生名字像王五的人
GET student/_doc/_search?q=name:王五
注意 这个名字类型如果是text就可以拆分 如果是keyword就不能拆分
权重大的就靠前
复杂搜索
分页
多条件查询
must 是俩个条件都满足 should 是满足任意一个
高亮显示
自动加了em 如何更改呢
SpringBoot整合ES
我们使用7.6.2版本的ES springboot默认使用6.8.7版本 肯定连不上
找到父项目的maven依赖 看到是6.8.2 在自己项目的properties下更改
向IOC注入自己的bean
@Bean
public RestHighLevelClient highLevelClient(){
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));
return restHighLevelClient;
}
测试
对索引增删查操作
对文档操作
把对象传输 就要转成json 所以引入json模块
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
package com.atguigu.lijiawei;
import com.alibaba.fastjson.JSON;
import com.atguigu.lijiawei.pojo.User;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import javax.naming.directory.SearchResult;
import java.io.IOException;
import java.util.Map;
@SpringBootTest
class LijiaweiApplicationTests {
@Autowired
@Qualifier("highLevelClient")
private RestHighLevelClient client;
@Test
void contextLoads() throws IOException {
//创建索引请求
CreateIndexRequest createIndexRequest = new CreateIndexRequest("student");
//执行
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
@Test
void contextLoads1() throws IOException {
//测试获取索引
GetIndexRequest Index = new GetIndexRequest("李嘉伟1");
boolean exists = client.indices().exists(Index, RequestOptions.DEFAULT);
System.out.println(exists);
}
@Test
void contextLoads2() throws IOException {
//测试删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("李嘉伟");
AcknowledgedResponse delete = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
System.out.println(delete);
}
@Test
void contextLoads3() throws IOException {
//测试添加文档
User u = new User("李嘉伟2",28);
//创建请求
IndexRequest request = new IndexRequest("student");
//指定规则
request.id("1");
//放入数据 对象无法直接传输 变成json
IndexRequest source = request.source(JSON.toJSONString(u), XContentType.JSON);
//发送请求
client.index(request,RequestOptions.DEFAULT);
}
@Test
void contextLoads4() throws IOException {
//测试获取文档
//创建请求
GetRequest getRequest = new GetRequest("student","2");
GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
Map<String, Object> source = getResponse.getSource();
System.out.println(source);
}
@Test
void contextLoads5() throws IOException {
//测试更新文档
//创建请求
UpdateRequest updateRequest = new UpdateRequest("student", "1");
User user = new User("李嘉伟", 15);
UpdateRequest doc = updateRequest.doc(JSON.toJSONString(user), XContentType.JSON);
client.update(doc, RequestOptions.DEFAULT);
}
@Test
void contextLoads6() throws IOException {
//测试更新文档
//创建请求
DeleteRequest deleteRequest = new DeleteRequest("student", "1");
client.delete(deleteRequest, RequestOptions.DEFAULT);
}
@Test
void contextLoads7() throws IOException {
//搜索
//创建请求
SearchRequest searchRequest = new SearchRequest("student");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//指定查询模式 比如匹配全部
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "李嘉伟");
searchSourceBuilder.query(termQueryBuilder);
searchRequest.source(searchSourceBuilder);
SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : search.getHits().getHits()) {
System.out.println(hit.getSourceAsMap());
}
}
}