package com.test.xulk.es.entity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.test.xulk.es.entity.Hotel;
public interface HotelMapper extends BaseMapper<Hotel> {
}
集成Springboot 项目里面
官方地址: Elasticsearch clients | Elastic Docs
引入依赖:由于需要链接数据库,所以也添加数据库相关依赖了
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<version>9.0.0</version>
<scope>runtime</scope>
</dependency>
<!--elasticsearch-->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<!--FastJson-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.71</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
配置文件
logging:
config: classpath:logback.xml
server:
port: 8081
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/es?useSSL=false
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
typeAliasesPackage: com.test.xulk.es.entity
mapperLocations: classpath*:mybatis/**/*Mapper.xml
global-config:
db-config:
logic-delete-value: 1 # 逻辑已删除值
logic-not-delete-value: 0 # 逻辑未删除值
创建实体类
package com.test.xulk.es.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("tb_hotel")
public class Hotel {
@TableId(type = IdType.INPUT)
private Long id;
private String name;
private String address;
private Integer price;
private Integer score;
private String brand;
private String city;
private String starName;
private String business;
private String longitude;
private String latitude;
private String pic;
}
Mapper接口
package com.test.xulk.es.entity.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.test.xulk.es.entity.Hotel;
public interface HotelMapper extends BaseMapper<Hotel> {
}
services的接口和实现类
package com.test.xulk.es.entity.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.test.xulk.es.entity.Hotel;
import com.test.xulk.es.entity.mapper.HotelMapper;
import com.test.xulk.es.entity.service.IHotelService;
import org.springframework.stereotype.Service;
@Service
public class HotelService extends ServiceImpl<HotelMapper, Hotel> implements IHotelService {
}
package com.test.xulk.es.entity.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.test.xulk.es.entity.Hotel;
public interface IHotelService extends IService<Hotel> {
}
创建索引
# address 不搜索 无需添加索引 "index": false
# 没必要分词 "type": "keyword", keyword是精准查询
PUT /hotel
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "ik_max_word"
},
"address": {
"type": "keyword",
"index": false
},
"price": {
"type": "integer"
},
"score": {
"type": "integer"
},
"brand": {
"type": "keyword"
},
"city": {
"type": "keyword"
},
"starName": {
"type": "keyword"
},
"business": {
"type": "keyword"
},
"location": {
"type": "geo_point"
},
"pic": {
"type": "keyword",
"index": false
}
}
}
}
# 由于有多个字段是相同的类型,分词也类似,为了提高效率,可以合成一个
name / brand / city / starName 都拷贝到all里面
# address 不搜索 无需添加索引 "index": false
# 没必要分词 "type": "keyword", keyword是精准查询
PUT /hotel
{
"mappings": {
"properties": {
"id": {
"type": "keyword"
},
"name": {
"type": "text",
"analyzer": "ik_max_word",
"copy_to": "all"
},
"address": {
"type": "keyword",
"index": false
},
"price": {
"type": "integer"
},
"score": {
"type": "integer"
},
"brand": {
"type": "keyword",
"copy_to": "all"
},
"city": {
"type": "keyword",
"copy_to": "all"
},
"starName": {
"type": "keyword",
"copy_to": "all"
},
"business": {
"type": "keyword"
},
"location": {
"type": "geo_point"
},
"pic": {
"type": "keyword",
"index": false
},
"all": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
es的映射对象
package com.test.xulk.es.esdoc;
import com.test.xulk.es.entity.Hotel;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class HotelDoc {
private Long id;
private String name;
private String address;
private Integer price;
private Integer score;
private String brand;
private String city;
private String starName;
private String business;
private String location;
private String pic;
}
索引库的操作示例代码
package com.test.xulk;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
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.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import java.io.IOException;
/**
* @program: spring-boot-mq-sentinel-xxl-es
* @author: xulk
* @create: 2025-06-02 10:43
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = HotelIndexTest.class)
public class HotelIndexTest {
private static final String MAPPING_TEMPLATE = "{\n" +
" \"mappings\": {\n" +
" \"properties\": {\n" +
" \"id\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"name\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"address\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"price\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"score\": {\n" +
" \"type\": \"integer\"\n" +
" },\n" +
" \"brand\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"city\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"starName\": {\n" +
" \"type\": \"keyword\",\n" +
" \"copy_to\": \"all\"\n" +
" },\n" +
" \"business\": {\n" +
" \"type\": \"keyword\"\n" +
" },\n" +
" \"location\": {\n" +
" \"type\": \"geo_point\"\n" +
" },\n" +
" \"pic\": {\n" +
" \"type\": \"keyword\",\n" +
" \"index\": false\n" +
" },\n" +
" \"all\": {\n" +
" \"type\": \"text\",\n" +
" \"analyzer\": \"ik_max_word\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
private RestHighLevelClient client;
// 快捷键 alt + inster 选择第二个 SetUp方法
// 初始化 client
@BeforeEach
void setUp() {
// // HttpHost.create("http://127.0.0.1:9200") // 若果是集群就配置多个
this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://127.0.0.1:9200")));
}
// 销毁
@AfterEach
void tearDown() throws IOException {
client.close();
}
// 测试初始化
/*@Test
void testInit() {
System.out.println(client);
}*/
// 创建索引库
@Test
void testCreateIndex() throws IOException {
// 1.准备Request PUT /hotel hotel 索引名
CreateIndexRequest request = new CreateIndexRequest("hotel");
// 2.准备请求参数
request.source(MAPPING_TEMPLATE, XContentType.JSON);
// 3.发送请求
client.indices().create(request, RequestOptions.DEFAULT);
}
// 删除索引库
@Test
void testDeleteIndex() throws IOException {
// 1.准备Request PUT /hotel hotel 索引名
DeleteIndexRequest request = new DeleteIndexRequest("hotel");
// 3.发送请求
client.indices().delete(request, RequestOptions.DEFAULT);
}
// 查询索引库
@Test
void testGetIndex() throws IOException {
// 1.准备Request PUT /hotel hotel 索引名
GetIndexRequest request = new GetIndexRequest("hotel");
// 3.发送请求
boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
System.out.println( exists ? "存在" : "不存在");
}
}
文档操作的示例代码
插入对比
@Test
void testAddDocument() throws IOException {
// 1.查询数据库hotel数据
Hotel hotel = hotelService.getById(61083L);
// 2.转换为HotelDoc
HotelDoc hotelDoc = new HotelDoc();
BeanUtils.copyProperties(hotel, hotelDoc);
hotelDoc.setLocation(hotel.getLatitude() + ", " + hotel.getLongitude());
// 3.转JSON
String json = JSON.toJSONString(hotelDoc);
// 1.准备Request
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
// 2.准备请求参数DSL,其实就是文档的JSON字符串
request.source(json, XContentType.JSON);
// 3.发送请求
client.index(request, RequestOptions.DEFAULT);
}
查询对比
// 查询文档
@Test
void testGetDocumentById() throws IOException {
// 1.准备Request
GetRequest request = new GetRequest("hotel", "61083");
// 2.准备请求参数DSL,其实就是文档的JSON字符串
GetResponse getResponse = client.get(request, RequestOptions.DEFAULT);
// 3.发送请求
String json = getResponse.getSourceAsString();
System.out.println( json );
}
删除
与查询相比,仅仅是请求方式从DELETE变成GET
// 删除文档
@Test
void testDeleteDocumentById() throws IOException {
// 1.准备Request // DELETE /hotel/_doc/{id}
DeleteRequest request = new DeleteRequest("hotel", "61083");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
修改对比
-
全量修改:本质是先根据id删除,再新增
-
增量修改:修改文档中的指定字段值
@Test
void testUpdateById() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("hotel", "61083");
// 2.准备修改的参数 修改哪个字段就写哪个字段
request.doc(
"price","100",
"score","45"
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
}
批量插入
// 批量插入/导入数据
@Test
void testBulkRequest() throws IOException {
// 1.查询数据库hotel数据
List<Hotel> list = hotelService.list();
BulkRequest bulkRequest = new BulkRequest();
for (Hotel hotel : list) {
HotelDoc hotelDoc = new HotelDoc();
// 1.构建参数
BeanUtils.copyProperties(hotel, hotelDoc);
hotelDoc.setLocation(hotel.getLatitude() + ", " + hotel.getLongitude());
// 3.转JSON
String json = JSON.toJSONString(hotelDoc);
// 4.创建新增文档的Request对象
IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString()).source(json, XContentType.JSON);
bulkRequest.add(request);
}
client.bulk(bulkRequest, RequestOptions.DEFAULT);
}
批量查询数据
GET /hotel/_search
数据库也是201条数据