当前位置: 首页 > article >正文

Elasticsearch 之 ElasticsearchRestTemplate 普通查询

前言:

上一篇我们分享了 Spring Boot 整合 Elasticsearch 使用 ElasticsearchRepository 完成简单的增删改查,我们发现 ElasticsearchRepository 中很多稍微复杂一些的查询就会显示方法过期,对于 Elasticsearch 7.X 版本,我们可以使用 ElasticsearchRestTemplate 来进行相关增删改查。

Elasticsearch 系列文章传送门

Elasticsearch 基础篇【ES】

Elasticsearch Windows 环境安装

QueryBuilders

QueryBuilders 是 Elasticsearch 中的一个工具类,用于构建各种复杂的查询的条件,在实际业务场景中,经常需要构建复杂的条件查询,如范围查询、布尔查询、模糊查询等场景,QueryBuilders 提供了构建这些复杂的查询能力,替代了手动编写复杂的 JSON 格式的查询 Elasticsearch 语句,在使用 ElasticsearchRestTemplate 完成 Elasticsearch 的各种复杂查询的时候,我们会使用到 QueryBuilders。

普通查询

ElasticsearchRestTemplate 是 Spring Data Elasticsearch 提供的一个操作 Elasticsearch 的模板类,它封装了在 Java 应用程序中执行各种 Elasticsearch 操作的方法,下面我们演示使用 ElasticsearchRestTemplate 来进行 Elasticsearch 的增删改查。

案例演示准备

我使用车作为业务模型进行 Elasticsearch 的 ElasticsearchRestTemplate 演示,车对象代码如下:

@Data
@Document(indexName = "car", shards = 1, replicas = 1)
public class CarDO {

    private Long id;

    private String color;

    private String model;

    private double price;

}

如上代码我们定义了一个 car 的索引关于车的相关文档都存储在了 car 这个索引中了。

save(保存文档)

ElasticsearchRestTemplate 使用 save 方法来保存单个文档,代码如下:

public void saveCar(CarDO carDO) {
	elasticsearchRestTemplate.save(carDO);
	List<CarDO> list = new ArrayList<>();
	list.add(carDO);
	elasticsearchRestTemplate.save(list);
}

可以看到 save 方法也是支持批量保存的。

get(查詢文档)

ElasticsearchRestTemplate 使用 get 方法根据文档 id 来查询文档,代码如下:

public CarDO queryCarById(Long id) {
	return elasticsearchRestTemplate.get(String.valueOf(id), CarDO.class);
}

我们传入了文档 id 和车对象的的 Class 即可根据文档 id 查询文档对象。

update(更新文档)

ElasticsearchRestTemplate 使用 update 方法来更新文档,代码如下:

public void updateCar(CarDO carDO) {
	UpdateQuery.Builder builder = UpdateQuery.builder(String.valueOf(carDO.getId()));
	Document document = Document.create();
	document.put("color", carDO.getColor());
	document.put("model", carDO.getModel());
	document.put("price", carDO.getPrice());
	builder.withDocument(document);
	elasticsearchRestTemplate.update(builder.build(), IndexCoordinates.of("car"));
}

可以看到 update 方法是根据 UpdateQuery 对象和索引名称来更新的。

bulkUpdate(批量更新文档)

ElasticsearchRestTemplate 使用 updbulkUpdate 方法来更新文档,代码如下:

public void batchUpdateCar(CarDO carDO) {
	UpdateQuery.Builder builder = UpdateQuery.builder(String.valueOf(carDO.getId()));
	Document document = Document.create();
	document.put("color", carDO.getColor());
	document.put("model", carDO.getModel());
	document.put("price", carDO.getPrice());
	builder.withDocument(document);
	List<UpdateQuery> updateQueryList = new ArrayList<>();
	updateQueryList.add(builder.build());
	elasticsearchRestTemplate.bulkUpdate(updateQueryList, IndexCoordinates.of("car"));
}

可以看到 bulkUpdate方法只是在 update 方法的基础上传入了 UpdateQuery List 对象来实现批量更新。

detele(删除文档)

ElasticsearchRestTemplate 使用 detele 方法来删除文档,代码如下:

public void detele(Long id) {
	CarDO carDO = new CarDO();
	carDO.setId(id);
	elasticsearchRestTemplate.delete(carDO);
}

ElasticsearchRestTemplate 删除文档的方法非常简单,传入对象即可根据文档 id 删除文档,,。

detele(批量删除文档)

ElasticsearchRestTemplate 批量删除文档同样是使用 delete 方法,代码如下:

public void batchDetele(String model) {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	queryBuilder.withQuery(QueryBuilders.matchQuery("model", model));
	elasticsearchRestTemplate.delete(queryBuilder.build(), CarDO.class);
}

可以看到批量删除使用 delete 方法的时候传入了一个 Query 对称。

PageRequest(分页查询文档)

ElasticsearchRestTemplate 分页查询依赖的是 PageRequest ,PageRequest 会构造一个分页对象来实现分页查询,代码如下:

public List<CarDO> pageList(int currentPage, int pageSize) {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	queryBuilder.withPageable(PageRequest.of(currentPage - 1, pageSize)).build();
	queryBuilder.withQuery(QueryBuilders.matchQuery("color", "雅灰"));
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

可以看到分页查询最终使用的是 search 方法。

SortBuilders(排序查询文档)

ElasticsearchRestTemplate 使用 withSort 来实现文档的查询排序,代码如下:

public List<CarDO> sortCar() {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	queryBuilder.withSort(SortBuilders.fieldSort("price").order(SortOrder.DESC));
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

可以看到我们在构造查询条件的时候使用 SortBuilders 来指定排序字段和排序方式,即可完成文档的排序查询。

rangeQuery(范围查询文档)

ElasticsearchRestTemplate 使用 rangeQuery 来实现按范围来查询文档来,代码如下:

public List<CarDO> priceRangeCar(double priceBegin, double priceEnd) {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	queryBuilder.withFilter(QueryBuilders.rangeQuery("price").gt(priceBegin).lt(priceEnd));
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

可以看到使用 QueryBuilders 构建查询条件的时候使用 rangeQuery 执行需要范围查询的字段,即可完成范围查询。

in 查询(同一个字段多条件查询)

ElasticsearchRestTemplate 使用 termsQuery 即可完成同一个字段的多条件查询,代码如下:

public List<CarDO> priceInCar(List<Double> priceList) {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	queryBuilder.withQuery(QueryBuilders.termsQuery("price", priceList));
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

可以看到我们在构建查询条件的时候,指定字段后传入一个 List 数组即可完成多条件查询,也就是类似 MySQL 的 in 查询。

or 查询

在真实项目的业务场景中 or 条件查询也是一种很场景的业务场景,ElasticsearchRestTemplate 使用 boolQuery 和多个 BoolQueryBuilder 拼接的方式来实现 or 条件的查询代码如下:

public List<CarDO> queryOrCar() {
	//(颜色:雅灰 and 价格:19.98) or (型号:su7)
	//or 使用 should
	//and 使用 must
	//not 使用 must_not
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	//(颜色:雅灰 and 价格:19.98)
	BoolQueryBuilder orOne = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("model", "xiaopeng")).must(QueryBuilders.termQuery("price", 19.98));
	//型号:su7
	BoolQueryBuilder orTwo = QueryBuilders.boolQuery().must(QueryBuilders.termQuery("model", "su7"));
	BoolQueryBuilder should = QueryBuilders.boolQuery().should(orOne).should(orTwo);
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.withQuery(should).build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

上述代码我们就完成了一个 [ (颜色:雅灰 and 价格:19.98) or (型号:su7) ] 这样一个 or 条件的查询。

ElasticsearchRestTemplate or 查询简单总结如下:

  • or 条件拼接使用 shoud。
  • and 使用 must。
  • not and 使用 must_not。

constantScoreQuery(评分查询文档)

constantScoreQuery 是 Elasticsearch 的一种查询类型,只不过这种查询类型略微有点特殊,用于在查询的时候指定一个固定的评分(默认是 1.0),而其他类型的查询如 termsQuery、matchQuery 是根据,文档的相关性来动态计算评分的,constantScoreQuery 的主要作用就是简化 Elasticsearch 的评分机制,高效的过滤文档,代码如下:

public List<CarDO> constantScoreQuery() {
	NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
	ConstantScoreQueryBuilder constantScoreQueryBuilder = QueryBuilders.constantScoreQuery(QueryBuilders.termQuery("model", "xiaopeng").boost(1.1f));
	SearchHits<CarDO> search = elasticsearchRestTemplate.search(queryBuilder.withQuery(constantScoreQueryBuilder).build(), CarDO.class);
	return search.getSearchHits().stream().map(SearchHit::getContent).collect(Collectors.toList());
}

总结:本篇我们使用了 ElasticsearchRestTemplate 实现了 Elasticsearch 的增删改查、分页、排序、范围、in or 等查询方法,ElasticsearchRestTemplate 操作简单且支持丰富的查询方法,是我们在 Spring 项目中操作 Elasticsearch 的好帮手,希望本篇的分享可以帮助到不是特熟悉 ElasticsearchRestTemplate 操作的朋友们,下一篇我将继续分享使用 ElasticsearchRestTemplate 进行更为复杂的聚合查询。

如有不正确的地方欢迎各位指出纠正。


http://www.kler.cn/a/611047.html

相关文章:

  • EMC知识学习一
  • 利用Openfeign远程调用第三方接口(案例:百度地图逆地理编码接口,实现通过经纬度坐标获取详细地址)
  • 【工具分享 - Redis桌面客户端】Tiny RDM
  • Linux:(模拟HTTP协议,GET和POST方法,Http的状态码)
  • DeepSeek概述
  • Spring Boot 整合 OpenFeign 教程
  • 游戏引擎 Unity - Unity 主要窗口(层级、场景、游戏、检查器、项目、 控制台)
  • node-ddk,electron,主进程通讯,窗口间通讯
  • 图解AUTOSAR_SWS_UDPNetworkManagement
  • 26考研——图_图的应用(6)
  • Maven工具学习使用(一)——MAVEN安装与配置
  • 企业级基于SpringBoot的MQTT的构建和使用
  • Vue3项目中的.vscode文件夹
  • 【软考-架构】9.3、端口扫描-安全体系-网络安全技术和协议
  • 海思烧录工具HITool电视盒子刷机详解
  • 初识MySQL · 约束
  • 【react18】react项目使用mock模拟后台接口
  • 【R语言可视化】人口金字塔
  • 游戏引擎学习第183天
  • 7.5 窗体事件