ES总结
1、ElasticSearch是高扩展的分布式的全文搜索引擎,它可以近乎实时的存储,检索数据
2、RESTful API风格,让搜索变得更简单
3、家族成员:
ElasticSearch:搜索服务应用程序
Logstash:是一个应用程序日志、事件的传输、处理、管理和搜索的平台
Kibana :是一个为 Logstash 和 ElasticSearch 提供的日志分析的 Web 接口
4、ES中的概念:
索引:类似于mysql的数据库
文档:类似于数据库中的一条信息
字段:信息中的某个字段
5、倒排索引:Inverted index
常被称为反向索引、置入档案或反向档案,是一种索引方法,被用来存储在全文搜索下某个单词在一个文档或者一组文档中的存储位置的映射。
它是文档检索系统中最常用的数据结构。
通过倒排索引,可以根据单词快速获取包含这个单词的文档列表
理解:
一个未经处理的数据库中,一般是以文档ID作为索引,以文档内容作为记录。
Inverted index 指的是将单词或记录作为索引,将文档ID作为记录,这样便可以方便地通过单词或记录查找到其所在的文档
6、IK分词器:
最小分词器:ik_smart (以这个词为粒度分词)精确查找
最小粒度分词器:ik_max_word (分出尽可能多的词) 包含查找
IK分词器:如果你搜索的词在IK分词器的词典中没有添加,可以将这个词添加到词典中,
之后再搜索就可以按照一个关键字来搜索,类似于关键字推广(seo优化)
7、查找功能:select(排序、分页、高亮、模糊查询、精准查询、字段过滤、范围过滤)
8、SpringBoot整合
编写配置类,与ES服务器链接获取ES客户端对象(低级客户端、高级客户端两种)
注入客户端对象,使用对象的API操作ES服务
ElasticSearch
简称ES,是一个开源的高扩展的分布式的全文搜索引擎,它可以近乎实时的存储,检索数据; 使用java开发,并且以lucene作为核心来实现索引和搜索的功能,通过RESTful API,让搜索变得更简单。
ELK
ELK是Elasticsearch、Logstash、Kibana三大开源框架,市面上也称Elastic Stack。
安装Elasticsearch
1、安装:https://www.elastic.co/cn/
华为云的镜像去下载
速度很快,自己找对应版本就可以
ElasticSearch: https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D
logstash: https://mirrors.huaweicloud.com/logstash/?C=N&O=D
kibana: https://mirrors.huaweicloud.com/kibana/?C=N&O=D
三个的版本要保证一致
2、查看目录
bin 启动文件
config 配置文件
log4j2 日志配置文件
jvm.options java虚拟机相关配置
elasticsearch.yml elastic相关配置文件 端口号:9200
lib 相关jar包
logs 日志
modules 功能模块
p'lugins 插件 ik分词器等
3、启动
启动bin目录下的 elasticsearch.bat文件
4、访问测试
访问127.0.0.1:9200
安装可视化插件
elasticsearch-head
https://github.com/mobz/elasticsearch-head
1、解压进入文件夹,输入安装命令 cnpm install
2、解压成功之后启动 npm run start
3、连接elastic:9200 发现跨域
配置解决elastic的跨域问题
找到config文件夹下的elasticsearch.yml,在文件的末尾添加如下内容:
http.cors.enabled: true
http.cors.allow-origin: "*"
4、重启elasticsearch
连接elasticsearch成功
安装Kibana
1、解压后的目录
2、启动
bin目录下的bat文件
访问 http://localhost:5601/
3、汉化
修改yml的配置文件
i18n.locale: "zh-CN"
4、重启
ES核心概念理解
ES中一切皆是JSON
索引
字段类型
文档
分片(倒排索引!)
索引:类似于数据库
types:慢慢会被弃用
documents: 文档
fields:文档中的一些字段
ES是面相文档的,一个索引可以有多个文档,索引和搜索数据的最小单元就是文档
文档的属性:
- 自我包含 key:value
- 层次:就是一个json对象{ }
IK分词器
分词器:即把一段中文或英文划分成一个个的关键字,在搜索的时候把信息进行分词,会把数据库中或者索引中的数据进行分词,进行匹配操作,默认的中文分词是将每一个字看成一个词,这显然不符合要求;如果使用中文检索,建议使用IK分词器
IK分词器提供了两种算法:ik_smart 和 ik_max_word;ik_smart 为最少切分,ik_max_word为最细粒度划分
1、下载
https://github.com/medcl/elasticsearch-analysis-ik/releases
官网太慢
https://pan.baidu.com/s/1WXX1t2kzwFRSEzJqx5Of5w 提取码4lbc
2、放入elasticsearch的插件新建ik目录,并解压
3、重启elasticsearch
4、bin目录下cmd输入命令 elasticsearch-plugin list 可以查看被加载的插件
5、使用kibana测试
最小分词器
最小粒度划分:穷尽词库的可能
如果自己需要的词被分开了,可以将这个词添加到分词器的字典中
IK分词器增加自己的配置
保存之后重启ES
索引的基本操作
创建索引
创建规则:单纯的创建一个索引,并设置索引中字段的值类型
获得索引信息
如果我们没有设置字段类型,没有规则
那么会给我们设置默认类型
扩展:
GET _CAT/...可以获取ES的更多信息
修改索引内容
1、put提交覆盖
2、post方式
删除索引
1、删除索引下的某个文档
2、删除某个索引
文档的基本操作(重点)
基本操作
1、新增数据
PUT kuangshen/user/1
{
"name": "王罕",
"age": 23,
"desc": "爱生活",
"tags": ["宅男","直男","爱女人"]
}
2、获取数据(get)
3、更新数据(put/post)
put为覆盖,如果要修改一个字段,其他字段也都要列进去,并且要保证值不变
推荐使用post方式更新,可以针对于某个字段更新
简单的搜索
GET /kuangshen/user/_search?q=name:张三
复杂操作
select(排序、分页、高亮、模糊查询、精准查询)
只查询其中某几个字段
GET /kuangshen/user/_search
{
"query": {
"match": {
"name": "狂神说"
}
},
"_source": ["name","desc"]
}
排序
GET /kuangshen/user/_search
{
"query": {
"match": {
"name": "狂神说"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
]
}
分页
GET /kuangshen/user/_search
{
"query": {
"match": {
"name": "狂神说"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 2
}
精准多条件查询
must(相当于sql中的and),所有的条件都要符合
should(相当于sql中的or),或的条件
must_not 不等于
过滤器
与must属性同级,增加过滤条件
GET /kuangshen/user/_search
{
"query": {
"bool": {
"must": [
{"match": {
"name": "狂神说"
}}
],
"filter": [
{"range": {
"age": {
"gte": 20,
"lte": 40
}
}}
]
}
}
}
匹配多个条件查询
精确查询
term查询是直接通过倒排索引指定的词条进程精确的查找的!
关于分词
term,直接查询精确的
match,会使用分词器解析(先分析文档,然后再通过分析的文档查询)
两个类型
text
keyword
精确查询多个值
高亮查询
hightlight字段与query同级
- 匹配
- 按照条件匹配
- 精确匹配
- 取见范围匹配
- 匹配字段过滤
- 多条件查询
- 高亮查询
我们之后使用java操作ES时,所有的对象和方法都是这里面的key
集成springboot
1、找到原生的依赖
ESClient客户端
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.6.2</version>
</dependency>
2、找对象
3、分析这个类中的方法
搭建项目,环境准备
jdk1.8
javascript必须为ECMAScript 6
问题:一定要保证我们导入的依赖与默认的版本一致(与ES服务器版本一致)
配置ElasticSearchClient
@Component
public class ElasticSearchClientConfig {
//使用的是高级客户端 也可以使用低级客户端的api
@Bean
public RestHighLevelClient restHighLevelClient() {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")
)
);
return client;
}
}
ElasticSearch 高级客户端API讲解
/*ElasticSearch 高级客户端API讲解*/
@SpringBootTest
class EsApiApplicationTests {
@Autowired
@Qualifier("restHighLevelClient")
private RestHighLevelClient client;
@Test
void creatIndex() throws IOException {
//索引的创建
CreateIndexRequest request = new CreateIndexRequest("kuangshen_index");
//客户端执行请求 index 的复数形式 indices;
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
System.out.println(createIndexResponse);
}
//获取索引,判断其是否存在
@Test
void getIndex() throws IOException {
GetIndexRequest index = new GetIndexRequest("kuangshen_index");
boolean exists = client.indices().exists(index, RequestOptions.DEFAULT);
System.out.println(exists);
}
//测试删除索引
@Test
void deleteIndex() throws IOException {
DeleteIndexRequest request = new DeleteIndexRequest("kuangshen_index");
AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
//测试添加文档
@Test
void addDocument() throws IOException {
//创建对象
User user = new User("wanghan", 20);
//创建请求
IndexRequest request = new IndexRequest("wanghan");
//规则 put /kuangshen/_doc/1
request.id("1");
// request.timeout("1s");
request.timeout(TimeValue.timeValueSeconds(1));
//将我们创建的对象放入请求
request.source(JSON.toJSONString(user), XContentType.JSON);
//客户端发送请求,获取响应结果
IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
System.out.println(indexResponse.toString());
System.out.println(indexResponse.status());
}
//获取文档 判断文档是否存在
@Test
void docIsExist() throws IOException {
GetRequest request = new GetRequest("wanghan", "1");
//不获取返回的_source上下文
request.fetchSourceContext(new FetchSourceContext(false));
request.storedFields("_none_");
boolean exists = client.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
//获取文档 判断文档是否存在
@Test
void getDocument() throws IOException {
GetRequest request = new GetRequest("wanghan", "1");
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
System.out.println(getResponse.getSourceAsString());//打印文档的内容
System.out.println(getResponse);//返回的内容和命令是一样的
}
//更新文档 判断文档是否存在
@Test
void updateDocument() throws IOException {
UpdateRequest request = new UpdateRequest("wanghan", "1");
request.timeout("1s");
User user = new User("lisi", 15);
request.doc(JSON.toJSONString(user), XContentType.JSON);
UpdateResponse updateResponse = client.update(request, RequestOptions.DEFAULT);
System.out.println(updateResponse.status());
}
//删除文档 判断文档是否存在
@Test
void deleteDocument() throws IOException {
DeleteRequest request = new DeleteRequest("wanghan", "1");
request.timeout("1s");
DeleteResponse deleteResponse = client.delete(request, RequestOptions.DEFAULT);
System.out.println(deleteResponse.status());
}
//真实的项目一般都会批量插入数据
@Test
void bulkRequest() throws IOException {
BulkRequest bulkRequest = new BulkRequest();
List<User> userList = new ArrayList<>();
userList.add(new User("aaa", 15));
userList.add(new User("bbb", 15));
userList.add(new User("ccc", 15));
for (int i = 0; i < userList.size(); i++) {
bulkRequest.add(
new IndexRequest("wanghan_bulk")
.id("" + (i + 1))
.source(JSON.toJSONString(userList.get(i)), XContentType.JSON));
}
client.bulk(bulkRequest,RequestOptions.DEFAULT);
}
//搜索
//搜索请求 SearchRequest
// 条件构造 SearchSourceBuilder
//构造高亮 highlighter
//精确查询 TermQueryBuilder
// 匹配所有模糊查询 MatchAllQueryBuilder
// xxxQueryBuilder对应我们所有的命令
@Test
void searchRequest() throws IOException {
SearchRequest searchRequest = new SearchRequest("wanghan_bulk");
//构建搜索条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//查询条件我们可以使用 QueryBuilders 工具来实现
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", "15");//精确查询
// MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();//匹配所有
sourceBuilder.query(termQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
for (SearchHit hit : searchResponse.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}
}
}
爬虫
数据问题,数据库获取,消息队列中获取,都可以成为数据源!
爬取数据(获取请求返回的页面信息,筛选出我们想要的数据就可以了)
详细教程看es-jd项目