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

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

相关推荐
面向星辰1 小时前
day07 spark sql
大数据·sql·spark
北邮-吴怀玉2 小时前
2.2.2.3 大数据方法论与实践指南-开源服务跟踪工具对比
大数据·开源
阿里云大数据AI技术2 小时前
云栖实录 | 阿里云助力金山办公打造智能搜索新标杆:WPS云文档搜索技术全面升级
人工智能·elasticsearch·搜索引擎
悠悠121383 小时前
Jenkins 从0基础到有点基础——如何安装
运维·jenkins
亚远景aspice3 小时前
亚远景热烈祝贺保隆科技通过ASPICE CL2评估
大数据·人工智能·物联网
赵谨言4 小时前
基于python大数据的城市扬尘数宇化监控系统的设计与开发
大数据·开发语言·经验分享·python
程序员小羊!4 小时前
Flink状态编程之算子状态(OperatorState)
大数据·flink
会飞的小蛮猪4 小时前
ELK运维之路(定时清理索引)
elasticsearch·kibana·logstash
TaoSense5 小时前
Milvus向量数据库介绍
大数据·人工智能
智海观潮5 小时前
聊聊Spark的分区
java·大数据·spark