探索Elasticsearch:文档的CRUD
在企业环境中,Elasticsearch对文档操作的支持不仅是实现高效搜索的关键,更是数据驱动决策的重要支柱。它通过强大的索引机制和灵活的查询语言,使企业能够实时处理和分析海量文档数据,迅速获取有价值的洞察,从而加速创新、优化运营并提升客户体验。 Elasticsearch让文档管理从简单的存储检索升级为智能信息发掘,成为现代企业不可或缺的数据处理引擎。
目录
文档的CRUD
基于Kibana控制台操作
新增文档
查询文档
修改文档
全量修改
局部修改
删除文档
基于Java REST Client 实现
准备依赖
准备实体类
初始化RestHighLevelClient
查询文档
删除文档
批处理操作文档
elasticsearch是面向文档(Document)存储的,可以是数据库中的一条商品数据,一个订单信息。文档数据会被序列化为json
格式后存储在elasticsearch
中。
上文中我们有了索引库,接下来就可以向索引库中添加数据了。
Elasticsearch中的数据其实就是JSON风格的文档。操作文档自然保护增
、删
、改
、查
等几种常见操作。
文档的CRUD
基于Kibana控制台操作
新增文档
# 新增文档
POST /user/_doc/1
{
"info": "我们都会找到好工作",
"email": "zy@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
实现效果如下:
查询文档
# 查询文档
GET /user/_doc/1
实现效果如下:
修改文档
全量修改
# 全量修改
PUT /user/_doc/1
{
"info": "我们都会找到幸福",
"email": "ZZZ@itcast.cn",
"name": {
"firstName": "云",
"lastName": "赵"
}
}
实现效果如下:
局部修改
# 局部修改Java
POST /user/_update/1
{
"doc": {
"email": "ZhaoYun@itcast.cn"
}
}
实现效果如下:
删除文档
# 删除文档
DELETE /user/_doc/1
实现效果如下:
基于Java REST Client 实现
准备依赖
上文导入了es的依赖
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.31</version>
</dependency>
<!-- mybatisPlus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!--hutool工具包-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.14</version>
</dependency>
准备一个数据库表(毕竟是测试,就建了一张表)
准备实体类
准备普通实体类Item和引库结构对应的实体类ItemDoc
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class Item implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
private Long id;
/**
* SKU名称
*/
private String name;
/**
* 价格(分)
*/
private Integer price;
/**
* 库存数量
*/
private Integer stock;
/**
* 商品图片
*/
private String image;
/**
* 类目名称
*/
private String category;
/**
* 品牌名称
*/
private String brand;
/**
* 规格
*/
private String spec;
/**
* 销量
*/
private Integer sold;
/**
* 评论数
*/
private Integer commentCount;
/**
* 是否是推广广告,true/false
*/
@TableField("isAD")
private Boolean isAD;
/**
* 商品状态 1-正常,2-下架,3-删除
*/
private Integer status;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 更新时间
*/
private LocalDateTime updateTime;
/**
* 创建人
*/
private Long creater;
/**
* 修改人
*/
private Long updater;
}
@Data
public class ItemDoc {
private String id;
private String name;
private Integer price;
private String image;
private String category;
private String brand;
private Integer sold;
private Integer commentCount;
@TableField("isAD")
private Boolean isAD;
private LocalDateTime updateTime;
}
准备一个ItemMapper
@Mapper
public interface ItemMapper extends BaseMapper<Item> {
}
创建一个测试类ElasticDocTest
初始化RestHighLevelClient
private RestHighLevelClient client;
@Autowired
private ItemMapper itemMapper;
/**
* 初始化ES客户端
*/
@BeforeEach
void setUp() {
client = new RestHighLevelClient(RestClient.builder(
HttpHost.create("http://自己的虚拟机地址:9200")
));
}
/**
* 关闭ES客户端
* @throws IOException
*/
@AfterEach
void tearDown() throws IOException {
if (client != null) {
client.close();
}
}
/**
* 测试连接
*/
@Test
void testConnection() {
System.out.println("client = " + client);
}
测试连接
连接ES客户端成功
新增文档
/**
* 新增文档
* @throws IOException
*/
@Test
void testIndexDoc() throws IOException {
// 1.根据id查询商品数据
Item item = itemMapper.selectById(11);
// 2.转换为文档类型
ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class); // 修改类名
// 3.将ItemDTO转json
String doc = JSONUtil.toJsonStr(itemDoc);
// 1.准备Request对象
IndexRequest request = new IndexRequest("items").id(itemDoc.getId());
// 2.准备Json文档
request.source(doc, XContentType.JSON);
// 3.发送请求
client.index(request, RequestOptions.DEFAULT);
}
查询文档
/**
* 根据id查询文档
* @throws IOException
*/
@Test
void testGetDocumentById() throws IOException {
// 1.准备Request对象
GetRequest request = new GetRequest("items").id("11");
// 2.发送请求
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.获取响应结果中的source
String json = response.getSourceAsString();
ItemDoc itemDoc = JSONUtil.toBean(json, ItemDoc.class);
System.out.println("itemDoc= " + itemDoc);
}
实现效果如下:
验证:新增文档和查询文档的成功了
修改文档
/**
* 根据id更新文档
* @throws IOException
*/
@Test
void testUpdateDocument() throws IOException {
// 1.准备Request
UpdateRequest request = new UpdateRequest("items", "11");
// 2.准备请求参数
request.doc(
"price", 66666,
"commentCount", 1
);
// 3.发送请求
client.update(request, RequestOptions.DEFAULT);
}
实现效果如下:(重新查询后与上图对比)
删除文档
/**
* 根据id删除文档
* @throws IOException
*/
@Test
void testDeleteDocument() throws IOException {
// 1.准备Request,两个参数,第一个是索引库名,第二个是文档id
DeleteRequest request = new DeleteRequest("items", "11");
// 2.发送请求
client.delete(request, RequestOptions.DEFAULT);
}
实现效果如下:(重新查询后与上图对比)
批处理操作文档
在之前的测试中,我们都是操作单个文档。而数据库中的商品数据实际会达到数十万条,某些项目中可能达到数百万条。
我们如果要将这些数据导入索引库,肯定不能逐条导入,而是采用批处理方案。
演示批量导入
@Test
void testLoadItemDoc() throws IOException {
// 分页查询商品数据
int pageNo = 1;
int size = 100;
while (true) {
// 查询当前页数据
Page<Item> page = itemService.lambdaQuery()
.eq(Item::getStatus, 1)
.page(new Page<>(pageNo, size));
// 获取当前页记录
List<Item> items = page.getRecords();
// 如果当前页没有数据,退出循环
if (CollUtil.isEmpty(items)) {
log.info("所有数据已加载完成");
break;
}
log.info("加载第{}页数据,共{}条", pageNo, items.size());
// 创建批量请求
BulkRequest request = new BulkRequest("items");
// 遍历当前页数据,添加到批量请求中
for (Item item : items) {
ItemDoc itemDoc = BeanUtil.copyProperties(item, ItemDoc.class);
request.add(new IndexRequest()
.id(itemDoc.getId())
.source(JSONUtil.toJsonStr(itemDoc), XContentType.JSON));
}
// 发送批量请求
client.bulk(request, RequestOptions.DEFAULT);
// 如果没有下一页数据,退出循环
if (!page.hasNext()) {
log.info("没有更多数据了");
break;
}
// 翻页
pageNo++;
}
}
实现效果如下:(主要我就准备了15条)