1.直击ES作用
遇到了什么问题?
随着互联网时代的蓬勃发展,网络上的数据量越来越丰富.用户的需求越来越特殊.
传统数据库(将数据存放在硬盘上的数据-mysql),不足以支撑复杂的搜索问题.技术的更新势在必行.
哪个技术可以解决这个问题?
ElasticSearch/solr: 非关系型数据库的一种
都是基于Lucene封装的.
Lucene是使用java语言编写的搜索引擎API
这个技术的使用方式?
安装:
创建索引库(表):
mapping映射(字段名,字段类型,字段约束,是否参与搜索..)
...
2.ES原理
正向索引
select * from 表名 where age = 18;
执行过程:
从数据库表中从上到下一条一条的取出数据,如果满足条件则留下此数据,如果不满足条件则忽略数据
倒排索引
倒排索引: 将被搜索的字段逐行遍历,并进行分词,建立词条与文档ID的对应关系
3.ES名词解释
词条(term): 一个中文词语就是一个词条(你好 数据库 我爱你)
文档(Document): 一条数据就是一个文档
索引(Index): 相同类型文档的集合
映射(Mapping): 索引中字段的约束信息
type: 字段类型
字符串类型:
text: 参与分词
keyword: 不参与分词
index: 字段是否参与搜索
默认值为true
analyzer: 是否分词
自带:
standard
IK:
ik_smart
ik_max_word
properties: 是否有子字段
4.ES使用
操作索引库和文档数据-DSL
# ES启动后就是一个web项目,直接向这个web项目发送RESTFul风格的请求即可操作es.
# RESTFul风格的请求:
# GET: 查询
# POST: 添加
# PUT: 修改
# DELETE: 删除
DSL
POST /_analyze
{
"text": "学习java太棒了"
}
PUT /house
GET /house
DELETE /house
# ES中自带的分词器叫standard(标准分词器),对中文不友好
POST /_analyze
{
"text": "中华人民共和国万岁",
"analyzer": "standard"
}
# 给ES安装ik分词器插件
# ik_smart: 聪明的
# ik_max_word: 最大词汇量分词
POST /_analyze
{
"text": "中华人民共和国万岁",
"analyzer": "ik_smart"
}
POST /_analyze
{
"text": "中华人民共和国万岁",
"analyzer": "ik_max_word"
}
POST /_analyze
{
"text": "哎哟呵奥利给风起来了",
"analyzer": "ik_max_word"
}
# 扩展词
# 停用词
#=====================索引库操作==================
# 创建索引库
# 创建空索引库
PUT /test
# 创建带有映射关系的索引
PUT /test
{
"mappings": {
"properties": {
"name":{
"type": "text",
"index": true,
"analyzer": "ik_smart"
},
"age":{
"type": "integer",
"index": true
},
"email":{
"type": "keyword",
"index": false
}
}
}
}
# 查看索引库
GET /test
# 查看索引库的映射信息
GET /test/_mapping
# 删除索引库
DELETE /test
# 修改索引库(通过修改索引库,添加新字段)
PUT /test/_mapping
{
"properties":{
"gender":{
"type":"keyword"
}
}
}
#===========================文档操作===================
# 添加文档数据
POST /test/_doc/1
{
"name":"大幂幂",
"age":18,
"gender":"女",
"email":"damimi@qq.com"
}
POST /test/_doc/1
{
"name":"大幂幂",
"age":18,
"gender":"女",
"email":"damimi@qq.com"
}
POST /test/_doc
{
"name":"大幂幂2",
"age":19,
"gender":"女",
"email":"damimi2@qq.com"
}
# 根据ID查询文档信息 // 6jP2yIoBwd3FfZ8R0WH0
GET /test/_doc/1
GET /test/_doc/XwYKH4kBS7Wd-2ayukAE
# 根据ID删除文档数据
DELETE /test/_doc/XwYKH4kBS7Wd-2ayukAE
# 修改-全量修改(覆盖)
PUT /test/_doc/1
{
"name":"大幂幂",
"age":18,
"gender":"女",
"email":"damimi@qq.com"
}
# 修改-增量修改(修改指定字段)
POST /test/_update/1
{
"doc":{
"name":"柳岩"
}
}
通过java代码操作ES
项目中导入ES依赖
高版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>WindTest</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>es</module>
</modules>
<!-- springboot父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.1</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>
低版本
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bw.es</groupId>
<artifactId>day0704-01-es</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- springboot父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<!-- 指定导入的es版本 -->
<elasticsearch.version>7.12.1</elasticsearch.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.12.1</version>
</dependency>
</dependencies>
</project>
创建ES核心对象
并将对象存放到ioc容器中
package com.wind;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.context.annotation.Bean;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
@Bean
public RestHighLevelClient createRestHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http")));
return client;
}
}
操作索引库
package com.wind.es;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.Map;
@SpringBootTest
public class test {
@Resource
private RestHighLevelClient esClient;
/*
//1.创建请求语义对象(本次访问es要做什么操作)
// 设置请求携带的参数
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
3.处理结果信息
todo:
java代码操作es的索引库
创建索引库
查看索引库
删除索引库
修改索引库
*/
@Test
//创建
public void addIndex() throws IOException {
//1.创建请求语义对象(本次访问es要做什么事情)
// CreateIndexRequest: 本次请求为的是创建索引
CreateIndexRequest request = new CreateIndexRequest("test2");
// 设置请求携带的参数
request.mapping("_doc", "{\n" + " "properties": {\n" + " "name":{\n" + " "type": "text",\n" + " "index": true,\n" + " "analyzer": "ik_smart"\n" + " },\n" + " "age":{\n" + " "type": "integer",\n" + " "index": true\n" + " },\n" + " "email":{\n" + " "type": "keyword",\n" + " "index": false\n" + " }\n" + " }\n" + " }", XContentType.JSON);
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);
//3.处理结果信息
boolean flag = response.isAcknowledged();
System.out.println(flag);
}
@Test
//查看
public void getIndex() throws IOException {
//1.创建请求语义对象(本次访问es要做什么操作)
GetIndexRequest request = new GetIndexRequest("test2");
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
GetIndexResponse response = esClient.indices().get(request, RequestOptions.DEFAULT);
//3.处理结果信息
Map<String, Object> map = response.getMappings().get("test2").getSourceAsMap();
System.out.println(map);
System.out.println(response);
}
@Test
//修改
public void updateIndex() throws IOException {
//1.创建请求语义对象(本次访问es要做什么操作)
PutMappingRequest request = new PutMappingRequest("test2");
//构建参数
request.source(
"{\n" +
" "properties": {\n" +
" "message": {\n" +
" "type": "text"\n" +
" }\n" +
" }\n" +
"}",
XContentType.JSON);
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
AcknowledgedResponse putMappingResponse = esClient.indices().putMapping(request, RequestOptions.DEFAULT);
//3.处理结果信息
boolean acknowledged = putMappingResponse.isAcknowledged();
System.out.println(acknowledged);
}
@Test
//删除
public void deleteIndex() throws IOException {
//1.创建请求语义对象(本次访问es要做什么操作)
DeleteIndexRequest request = new DeleteIndexRequest("test2");
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
AcknowledgedResponse deleteIndexResponse = esClient.indices().delete(request, RequestOptions.DEFAULT);
//3.处理结果信息
boolean acknowledged = deleteIndexResponse.isAcknowledged();
System.out.println(acknowledged);
}
@Test
//查看索引是否存在
public void isOK() throws IOException {
//1.创建请求语义对象(本次访问es要做什么操作)
GetIndexRequest request = new GetIndexRequest("test2");
//2.发送请求给ES
// RequestOptions.DEFAULT: 使用默认的请求方式
boolean exists = esClient.indices().exists(request, RequestOptions.DEFAULT);
//3.处理结果信息
System.out.println(exists);
}
}
文档操作
准备工作
application.yml
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
map-underscore-to-camel-case: true
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/wind_test?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
username: root
password: 123456
logging:
level:
root: info
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>WindTest</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>com.wind</groupId>
<artifactId>es</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- mp依赖-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 解析json-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.32</version>
</dependency>
<!-- 减少重复代码插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
package com.wind.es;
import com.alibaba.fastjson.JSON;
import com.wind.domain.TestIndex;
import com.wind.service.TestIndexService;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
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.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.List;
@SpringBootTest
public class DocTest {
@Resource
private RestHighLevelClient client;
@Resource
private TestIndexService service;
/**
* //1.创建请求语义对象(本次访问es要做什么操作)
* // 设置请求携带的参数
* //2.发送请求给ES
* // RequestOptions.DEFAULT: 使用默认的请求方式
*
* //3.处理结果信息
*
* todo:
* java代码操作es中的文档数据
* 添加文档数据
* 查看文档数据
* 删除文档数据
* 修改文档数据
* for批量插入
* bulk批量插入
* 6zMByYoBwd3FfZ8R_WG4
*/
@Test
//添加文档数据
public void insertDoc() throws IOException {
//创建请求语义对象
IndexRequest request = new IndexRequest("test");
//构建参数
String jsonString = "{" +
""name":"奶茶妹"," +
""age":"18"," +
""gender":"男"," +
""email":"fengqi@163.com"" +
"}";
TestIndex testIndex = new TestIndex();
testIndex.setName("风起");
testIndex.setAge(18);
String s = JSON.toJSONString(testIndex);
request.source(testIndex, XContentType.JSON);
//发送请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
//解析返回结果
System.out.println(response.status());
System.out.println(response.getResult());
}
@Test
//根据id查看文档
public void getIndexDoc() throws IOException {
//创建请求语义对象
GetRequest request = new GetRequest(
"test",
"5DOHyIoBwd3FfZ8Rp2Gv");
//发送请求
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String sourceAsString = response.getSourceAsString();
System.out.println(sourceAsString);
TestIndex testIndex = JSON.parseObject(sourceAsString, TestIndex.class);
System.out.printf("---------------------");
System.out.println(testIndex);
}
//修改
@Test
public void updateDoc() throws IOException {
//创建请求语义对象
UpdateRequest request = new UpdateRequest("test","5DOHyIoBwd3FfZ8Rp2Gv");
//构建参数
TestIndex testIndex = new TestIndex();
testIndex.setName("吴彦祖");
testIndex.setAge(111);
testIndex.setGender("男");
testIndex.setEmail("吴彦祖163.com");
String jsonString = "{" +
""name":"奶茶妹"," +
""age":"18"," +
""gender":"男"," +
""email":"fengqi@163.com"" +
"}";
request.doc(jsonString,XContentType.JSON);
//发送请求
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println(response.status());
}
//删除
@Test
public void delDoc() throws IOException {
//创建请求语义对象
DeleteRequest request = new DeleteRequest("test", "5DOHyIoBwd3FfZ8Rp2Gv");
//发送请求给es
DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
//解析返回结果
System.out.println(delete.status());
}
@Test
//基于for循环的批量插入
public void insertListDoc() throws IOException {
List<TestIndex> list = service.list();
for (TestIndex testIndex : list) {
//创建语义对象
IndexRequest request = new IndexRequest("test");
//构建参数
request.id(testIndex.getId()+"");
request.source(JSON.toJSONString(testIndex),XContentType.JSON);
//向es发送请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
//解析结果
System.out.println(response.status());
}
}
@Test
public void BulkDoc() throws IOException {
//创建请求语义对象
BulkRequest bulkRequest = new BulkRequest("test");
//mysql中获取数据
List<TestIndex> list = service.list();
for (TestIndex testIndex : list) {
//创建请求语义对象
IndexRequest request = new IndexRequest();
//构建参数
request.source(JSON.toJSONString(testIndex), XContentType.JSON);
//添加到bulk处理中
bulkRequest.add(request);
}
//向es发送请求
BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
System.out.println(bulk.status());
}
}