0. Es的概念
- es是基于lucene的搜索服务器
- 是一个分布式、高扩展、高实时的搜索数据分析引擎
- 基于restful接口
- 开源!基于java 开发的
应用场景主要是 海量数据的搜索、日志数据的分析、实时数据的分析。
1. ES的痛点
ES 是一个搜索服务器,那么为什么会有这个搜索服务的器功能呢?那肯定是因为我们的sql 查询满足不了一些相关的搜索。
- 在数据量特别大的时候,用Like ‘%xx’ 这样的语句会让索引失效,进而会非常慢!
- 我们百度的时候,可以观察一下,搜苹果手机,前面肯定都是匹配的苹果手机四个字,但是越往后就是,苹果和手机了。我要实现这样的功能,关系型数据库的搜索是无法满足的。
1.2 Es的倒排索引
有倒排就有正排索引。
我们在学生时代的时候语文有一个题形,简单的就是比如 故人西辞黄鹤楼 下一句是什么。难的怎么考,比如落霞与孤鹜齐飞上一句是什么?有的小伙伴就蒙圈了。我们背书的时候,习惯就是从上一句背到下一句,某种意义上,上一句就是下一句的索引,很快啊!就可以在大脑了里查出来,但是后一句问上一句,就不行了,猪脑直接过载,为什么因为我们没有创建这个倒排索引。
当然这边只是让大家理解这个意思,真正体现到数据库的就是我关键字当索引。
1.3 Es 存储方式
对于关系型数据库里的数据,es 这边称之为一个document ,每个document的某个字段会通过分词器分完之后和document存储一个关联关系,当然一个词会和多个document关联上关系。我们查询某个词汇的时候也会将这个词汇先进行分词,然后通过这个分词去查找对应的document。
2. es的安装
开始实操!下载地址
我这边选用的是linux 版本安装,我的版本是elasticsearch-7.4.0,注意我这边的配置只针对这个版本。es 是用java 语言编写的,下面我改了一下es 的配置文件elasticsearch.yml
cluster.name: my-application #名称
node.name: node-zx #节点名称
network.host: 0.0.0.0 #是否能远程访问
http.port: 9200 #端口
cluster.initial_master_nodes: ["node-zx"] #主节点
我的虚拟机是1g的内存不够,就改了运行内存大小,从1g -> 512m,如果内存不够就会直接闪退。也不会报错。
这边的注意点就是不能用root用户启动,得申请一个用户,然后把es赋权给这个用户,最后启动一下就行。
2.1 kibana 官方插件工具
下载地址 我这边的版本还是7.4.0
解压命令
tar -zxvf kibana-7.4.0-linux-x86_64.tar.gz
修改配置,都是常规配置。
server.port: 5601
server.host: "0.0.0.0"
server.name: "kib"
elasticsearch.hosts: ["http://127.0.0.1:9200"]
elasticsearch.requestTimeout: 99999
3.操作索引
因为是restful风格,这边用postman 操作就行
4 kibana 操作映射
5.操作文档
增删改查所有操作。
6 分词器
标准分词器效果演示,这种对于中文来说非常不友好,这个对于英文来说还行。
6.1 IK分词器
首先下载安装maven 下载地址,这一步不是很重要。
再次下载IK分词器的安装包 下载地址
下完了之后在/www/wwwroot/elasticsearch-7.4.0/plugins
在这个目录创建一个自己的文件夹,把压缩IK的分词器的包放入这个文件夹解压。
然后把这个解压出来的config文件放入es的config文件夹下,重启es 就大功告成了
下面就是用IK分词器的两种写法
6.1.1 ik 查询
# 普通查询就是一个字一个字德查询term 查询
#这个查询就是按照词条去查询
GET yxlm/_search
{
"query":{
"term": {
"country": {
"value": "北京靖江"
}
}
}
}
#这边的查询就是会将你的查询条件进行分词之后再去查询
#这样就可以查询
GET yxlm/_search
{
"query":{
"match": {
"country": "南京靖江"
}
}
}
#创建索引的时候记住用ik 自带的分词器
PUT /yxlm
{
"mappings":{
"properties":{
"name":{
"type":"text"
},
"age":{
"type":"integer"
},
"country":{
"type":"text",
"analyzer":"ik_max_word"
}
}
}
}
#然后给索引添加数据,其实就是将这个数据和索引进行一个关联关系的绑定
POST yxlm/_doc
{
"name":"beij" ,
"country":"我家住在靖江",
"age":12
}
DELETE yxlm
以上就是ik分词器结合es的使用。
7. springboot 操作es
7.0 首先是pom文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.4.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.4.0</version>
</dependency>
</dependencies>
7.1 配置类
注意这边的参数是配置在配置文件里面的
package com.example.config;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class EsConfig {
private String host;
private int port;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
@Bean
public RestHighLevelClient getEsClient(){
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(
new HttpHost(host,port,"http")
));
return restHighLevelClient;
}
}
7.2 操作索引
这边就是索引的增删改查询操作
package com.example;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.IndicesClient;
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.client.indices.GetIndexResponse;
import org.elasticsearch.cluster.metadata.MappingMetaData;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = EsApplication.class)
public class EsApplicationTest {
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void esTest(){
// RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(
// new HttpHost("124.223.99.145",9200,"http")
// ));
System.out.println(restHighLevelClient);
}
//这个仅仅就是添加索引,还没有添加索引的相关检索字段
@Test
public void addIndex() throws IOException {
//操作索引
IndicesClient indices = restHighLevelClient.indices();
//创建索引
CreateIndexRequest index = new CreateIndexRequest("china");
//创建返回值
CreateIndexResponse createIndexResponse = indices.create(index, RequestOptions.DEFAULT);
boolean acknowledged = createIndexResponse.isAcknowledged();
System.out.println(acknowledged);
}
/**
* 添加索引以及对应的属性,这边的属性就是,对象分词的一些东西
* @throws IOException
*/
@Test
public void addIndexAndMapping() throws IOException {
//操作索引
IndicesClient indices = restHighLevelClient.indices();
//创建索引,注意这边的对象有两个差不多的,用新款对象,老款对象的方法已经废弃了,注意分别
CreateIndexRequest index = new CreateIndexRequest("chinaandmapping");
//处理索引的属性
index.mapping("{\n" +
" \"properties\" : {\n" +
" \"age\" : {\n" +
" \"type\" : \"integer\"\n" +
" },\n" +
" \"country\" : {\n" +
" \"type\" : \"text\",\n" +
" \"analyzer\" : \"ik_max_word\"\n" +
" },\n" +
" \"name\" : {\n" +
" \"type\" : \"text\"\n" +
" }\n" +
" }\n" +
" }",XContentType.JSON);
//创建返回值
CreateIndexResponse createIndexResponse = indices.create(index, RequestOptions.DEFAULT);
boolean acknowledged = createIndexResponse.isAcknowledged();
System.out.println(acknowledged);
}
@Test
public void queryIndex() throws IOException {
//操作索引
IndicesClient indices = restHighLevelClient.indices();
GetIndexRequest index = new GetIndexRequest("chinaandmapping");
GetIndexResponse getIndexResponse = indices.get(index, RequestOptions.DEFAULT);
Map<String, MappingMetaData> mappings = getIndexResponse.getMappings();
for(String key : mappings.keySet()){
System.out.println(key+ mappings.get(key).getSourceAsMap());
}
}
@Test
public void deleteIndex() throws IOException {
//操作索引
IndicesClient indices = restHighLevelClient.indices();
DeleteIndexRequest index = new DeleteIndexRequest("chinaandmapping");
AcknowledgedResponse delete = indices.delete(index, RequestOptions.DEFAULT);
System.out.println(delete.isAcknowledged());
}
@Test
public void getIndex() throws IOException {
//操作索引
IndicesClient indices = restHighLevelClient.indices();
GetIndexRequest request = new GetIndexRequest("chinaandmapping");
boolean exists = indices.exists(request, RequestOptions.DEFAULT);
System.out.println(exists);
}
}
7.3 操作文档
/**
* 添加文档 对象
* @throws IOException
*/
@Test
public void addDocByObj() throws IOException {
YxlmObj yxlm = new YxlmObj();
yxlm.setAge(2);
yxlm.setCountry("我家住在山西县");
yxlm.setName("李云龙222");
yxlm.setId("2");
IndexRequest yxlmindex = new IndexRequest("yxlm").id(yxlm.getId()).source(JSON.toJSONString(yxlm),XContentType.JSON);
IndexResponse index = restHighLevelClient.index(yxlmindex, RequestOptions.DEFAULT);
System.out.println(index.getId());
}
@Test
public void updateDocByObj() throws IOException {
//修改就是上面的增加,如果id是一样的就会是修改操作
}
/**
* 查询操作
* @throws IOException
*/
@Test
public void findDocByObj() throws IOException {
GetRequest getRequest = new GetRequest("yxlm","1");
GetResponse documentFields = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
String sourceAsString = documentFields.getSourceAsString();
System.out.println(sourceAsString);
}
@Test
public void deleteDocByObj() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("yxlm","1");
DeleteResponse delete = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
String id = delete.getId();
System.out.println(id);
}