初识 ElasticSearch
- ElasticSearch是一个搜索服务器
数据库存在的问题
- 数据库查询的问题
性能低
功能弱
倒排索引
- 倒排索引:将各个文档中的内容,进行分词,形成词条。然后记录词条和数据的唯一标识(id)的对 应关系,形成的产物。
ElasticSearch概念
- ElasticSearch是一个基于Lucene的搜索服务器
- 是一个分布式、高扩展、高实时的搜索与数据分析引擎
- 基于RESTful web接口
- Elasticsearch是用Java语言开发的,并作为Apache许可条款下的开放源码发布,是一种 流行的企业级搜索引擎
- 官网:https://www.elastic.co/
应用场景 :
- 搜索:海量数据的查询
- 日志数据分析
- 实时数据分析
• MySQL有事务性,而ElasticSearch没有事务性,所以你删了的数据是无法恢复的。
• ElasticSearch没有物理外键这个特性,,如果你的数据强一致性要求比较高,还是建议慎用
ElasticSearch和MySql分工不同,MySQL负责存储数据,ElasticSearch负责搜索数据
以前的架构:
现在的架构:
小结
- 数据库查询存在的问题
• 性能低
• 功能弱 - 倒排索引
• 将文档进行分词,形成词条和id的对应关系。 - ElasticSearch概念及作用
• 搜索服务器
• 高性能,功能强大
• 不是替换mysql,是与mysql分工不同,es做搜索,mysql做数据存储
ElasticSearch数据的存储和搜索原理
安装 ElasticSearch
本文使用的ElasticSearch基于docker容器安装
注意: ElasticSearch , kibana , ik 分词器需要使用同一个版本号
ElasticSearch 核心概念
操作 ElasticSearch
RESTful风格
操作索引
- 添加索引
PUT http://ip:端口/索引名称 - 查询索引
GET http://ip:端口/索引名称 # 查询单个索引信息
GET http://ip:端口/索引名称1,索引名称2… # 查询多个索引信息
GET http://ip:端口/_all # 查询所有索引信息 - 删除索引
DELETE http://ip:端口/索引名称 - 关闭索引
POST http://ip:端口/索引名称/_close - 打开索引
POST http://ip:端口/索引名称/_open
操作映射
- 简单数据类型
- 复杂数据类型
数组:[]
对象:{}
kibana 操作映射:
- 添加映射
- 查询映射
- 添加字段
操作文档
分词器
IK分词器
• IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包
• 是一个基于Maven构建的项目
• 具有60万字/秒的高速处理能力
• 支持用户词典扩展定义
• 下载地址:https://github.com/medcl/elasticsearch-analysis-ik/archive/v7.4.0.zip
IK分词器使用
ik分析器, 细粒度:
GET _analyze
{
“analyzer”: “ik_max_word”
,“text”: “我爱北京天安门”
}
ik分析器, 粗粒度
GET _analyze
{
“analyzer”: “ik_smart”
,“text”: “我爱北京天安门”
}
查询文档
- 词条查询:term
• 词条查询不会分析查询条件,只有当词条和查询字符串完全匹配时才匹配搜索 - 全文查询:match
• 全文查询会分析查询条件,先将查询条件进行分词,然后查询,求并集
当字段类型为text时,需要指定分析器为ik的分词器,否则默认为standard,它对中文不友好,它是按照空格分词
ElasticSearch JavaAPI
SpringBoot 整合 ES
由于elasticsearch对于Springboot来说没有一个单独的启动类,所以整合时使用spring对应的es的相关依赖即可
配置文件application.yml:
elasticsearch:
host: 192.168.23.139
port: 9200
配置类ElasticSearchConfig:
package com.itheima.esdemo.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;
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig {
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 client(){
return new RestHighLevelClient(RestClient.builder(
new HttpHost(
host,
port,
"http"
)
));
}
}
测试类:
package com.itheima.esdemo;
import com.alibaba.fastjson.JSON;
import com.itheima.domain.Person;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
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.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@SpringBootTest
class EsDemoApplicationTests {
@Autowired
private RestHighLevelClient client;
@Test
void contextLoads() {
//1.创建es客户端
/*RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
new HttpHost(
"192.168.23.139",
9200,
"http"
)
));
*/
System.out.println(client);
}
/**
* 添加索引
*/
@Test
public void addIndex() throws IOException {
//1.使用client获取操作索引的对象
IndicesClient indicesClient = client.indices();
//2.具体的操作,获取返回值
CreateIndexResponse response = indicesClient.create(new CreateIndexRequest("itheima"), RequestOptions.DEFAULT);
//3.根据返回值判断结果
System.out.println(response.isAcknowledged());
}
/**
* 添加索引和映射
*/
@Test
public void addIndexAndMapping() throws IOException {
//1.使用client获取操作索引的对象
IndicesClient indicesClient = client.indices();
//2.具体的操作,获取返回值
CreateIndexRequest createIndexRequest = new CreateIndexRequest("itcast");
//2.1 设置mappings
String mapping = "{\n" +
" \"properties\" : {\n" +
" \"address\" : {\n" +
" \"type\" : \"text\",\n" +
" \"analyzer\" : \"ik_max_word\"\n" +
" },\n" +
" \"age\" : {\n" +
" \"type\" : \"long\"\n" +
" },\n" +
" \"name\" : {\n" +
" \"type\" : \"keyword\"\n" +
" }\n" +
" }\n" +
" }";
createIndexRequest.mapping(mapping, XContentType.JSON);
CreateIndexResponse response = indicesClient.create(createIndexRequest, RequestOptions.DEFAULT);
//3.根据返回值判断结果
System.out.println(response.isAcknowledged());
}
/**
* 查询索引
*/
@Test
public void queryIndex() throws IOException {
IndicesClient indices = client.indices();
GetIndexResponse response = indices.get(new GetIndexRequest("itcast"), RequestOptions.DEFAULT);
//过去结果
Map<String, MappingMetaData> mappings = response.getMappings();
for (String key : mappings.keySet()) {
System.out.println(key+":"+mappings.get(key).getSourceAsMap());
}
}
/**
* 删除索引
*/
@Test
public void deleteIndex() throws IOException {
IndicesClient indices = client.indices();
AcknowledgedResponse response = indices.delete(new DeleteIndexRequest("itheima"), RequestOptions.DEFAULT);
System.out.println(response.isAcknowledged());
}
/**
* 判断索引是否存在
*/
@Test
public void existIndex() throws IOException {
IndicesClient indices = client.indices();
boolean exists = indices.exists(new GetIndexRequest("itcast"), RequestOptions.DEFAULT);
System.out.println(exists);
}
/**
* 添加文档,使用map作为数据
*/
@Test
public void addDoc() throws IOException {
//数据对象,map
Map data = new HashMap();
data.put("address","北京昌平");
data.put("name","大胖");
data.put("age",20);
//1.获取操作文档的对象
IndexRequest request = new IndexRequest("itcast").id("1").source(data);
//添加数据,获取结果
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
//打印响应结果
System.out.println(response.getId());
}
/**
* 添加文档,使用对象作为数据
*/
@Test
public void addDoc2() throws IOException {
//数据对象,javaObject
Person p = new Person();
p.setId("2");
p.setAge(30);
p.setAddress("重庆");
//将对象转为json
String data = JSON.toJSONString(p);
//1.获取操作文档的对象
IndexRequest request = new IndexRequest("itcast").id(p.getId()).source(data, XContentType.JSON);
//添加数据,获取结果
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
//打印响应结果
System.out.println(response.getId());
}
/**
* 根据id查询文档
*/
@Test
public void findDocById() throws IOException {
GetRequest request = new GetRequest("itcast", "1");
//getRequest.id("1")
GetResponse response = client.get(request, RequestOptions.DEFAULT);
//获取数据对应的json
System.out.println(request);
}
/**
* 根据id删除文档
*/
@Test
public void delDoc() throws IOException {
DeleteRequest deleteRequest = new DeleteRequest("itcast", "1");
DeleteResponse response = client.delete(deleteRequest, RequestOptions.DEFAULT);
System.out.println(response.getId());
}
}