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 演示,车对象代码如下:

java 复制代码
@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 方法来保存单个文档,代码如下:

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

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

get(查詢文档)

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

java 复制代码
public CarDO queryCarById(Long id) {
	return elasticsearchRestTemplate.get(String.valueOf(id), CarDO.class);
}

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

update(更新文档)

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

java 复制代码
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 方法来更新文档,代码如下:

java 复制代码
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 方法来删除文档,代码如下:

java 复制代码
public void detele(Long id) {
	CarDO carDO = new CarDO();
	carDO.setId(id);
	elasticsearchRestTemplate.delete(carDO);
}

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

detele(批量删除文档)

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

java 复制代码
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 会构造一个分页对象来实现分页查询,代码如下:

java 复制代码
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 来实现文档的查询排序,代码如下:

java 复制代码
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 来实现按范围来查询文档来,代码如下:

java 复制代码
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 即可完成同一个字段的多条件查询,代码如下:

java 复制代码
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 条件的查询代码如下:

java 复制代码
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 的评分机制,高效的过滤文档,代码如下:

java 复制代码
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 进行更为复杂的聚合查询。

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

相关推荐
D愿你归来仍是少年5 分钟前
使用 PySpark 批量清理 Hive 表历史分区
大数据·数据仓库·hive·spark
End92837 分钟前
Hadoop的三大结构及其作用?
大数据·hadoop·分布式
云攀登者-望正茂1 小时前
Jenkins 多分支流水线: 如何创建用于 Jenkins 状态检查的 GitHub 应用
云原生·github·jenkins
chat2tomorrow3 小时前
数据仓库 vs 数据湖:架构、应用场景与技术差异全解析
大数据·数据仓库·低代码·架构·数据湖·sql2api
塔能物联运维3 小时前
双轮驱动能源革命:能源互联网与分布式能源赋能工厂能效跃迁
大数据·运维
-曾牛4 小时前
Git Flow
大数据·git·学习·elasticsearch·个人开发
461K.4 小时前
spark与hadoop的区别
大数据·运维·hadoop·分布式·spark·intellij-idea
Zfox_4 小时前
Git 进阶之路:高效协作之分支管理
大数据·linux·运维·c++·git·elasticsearch
lilye664 小时前
精益数据分析(11/126):辨别虚荣指标,挖掘数据真价值
大数据·人工智能·数据分析
白鲸开源5 小时前
万字长文 | Apache SeaTunnel 分离集群模式部署 K8s 集群实践
大数据