开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情
1.查询过程
因为本专栏只讲实战,理论性的东西只稍微讲一下
我们现在是在集群上新建的索引,之前的新建索引的时候我们是设置了分片是3,也即是说数据会根据Es的分片算法,将3份数据分布在各个机器上。
比如现在有三条数据,分了三个shard,每个机器一个shard, 当我们发起一个查询的时候,查询流程大致如下:
1.客户端将查询请求发送到master节点
2.master节点将查询请求发送到索引的各个分片中
3.每个分片在本地执行查询逻辑
4.每个分片将查询结果返回给master节点,由master节点进行合并
2.1 范围查询的一些基础
范围查询主要是用于匹配某些字段的字段值位于特定范围内的文档。
范围查询接收以下参数
- gt:大于
- gte:大于等于
- lt:小于
- lte:小于等于
- format:用于转换日期查询中值类型为date数据的格式
- time_zone:时区,默认的是美国时区,中国时间查询时候我们需要加上Asia/Shanghai
- boost:相关性,值是float类型,默认相关性是1.0,我们查处的结果会有一个_score字段,它代表的意思就是查询条件跟结果的相关性得分
2.2 普通范围查询
比如我们要查询商品价格在10-15元范围内的商品价格,DSL实现如下
GET /goods_item_index/_search
{
"query": {
"range": {
"basePrice": {
"gte": 10,
"lte": 15
}
}
}
}
2.3 日期范围查询
查询更新时间在2008-01-01 00:00:00到2010-01-01 00:00:00这个时间范围内的商品数据,DSL实现如下
GET /goods_item_index/_search
{
"query": {
"range": {
"updateTime": {
"gte": "2008-01-01 00:00:00",
"lte": "2010-01-01 00:00:00",
"format": "yyyy-MM-dd HH:mm:ss",//如期格式
"time_zone": "Asia/Shanghai" //上海时区
}
}
}
}
2.4 Date Math日期数学表达式
当我们使用gt、gte、lt、lte这几个比较参数的时候,我们可以使用日期数学表达式来进行日期的比较。
支持的时间单位为包含如下几项
- y:年
- M:月
- w:周
- d:天
- h:小时
- H:小时
- m:分钟
- s:秒
表达式通常的操作会是这样
- +1d,表示加上一天
- -15y,表示减去15年
- /d,表示向一天取整
举几个例子:
- now-14y/y,表示当前时间减去14年,并向一年取整
- now+1h+1m,表示当前时间加上一个小时零一分钟
- 2008-08-01 00:00:00||-1M/d,表示2008-08-01减去一个月,并向一天取整
假如我们要查询从现在开始,查询过去14年的数据,DSL表达式如下
GET /goods_item_index/_search
{
"query": {
"range": {
"updateTime": {
"gte": "now-14y/y",
"lte": "now/y"
}
}
}
}
假如我们要查询小于2008-08-01 00:00:00开始减去一个月的时间,且大于2008-06-01 00:00:00这个时间点的数据,DSL如下
GET /goods_item_index/_search
{
"query": {
"range": {
"updateTime": {
"gte": "2008-06-01 00:00:00",
"lte": "2008-08-01 00:00:00||-1M/d"
}
}
}
}
3. 基于Java Api实现
我们在com.daiyu.elastic.service.GoodsService新增范围查询方法
/**
* 日期范围查询
*
* @param startTime 开始时间
* @param endTime 结束时间
* @return 返回结果集
*/
List<GoodsItemRep> queryByDateRange(String startTime, String endTime);
/**
* 标签价格范围查询
*
* @param minPrice 最小价格
* @param maxPrice 最大价格
* @return 返回结果集
*/
List<GoodsItemRep> queryByPriceRange(String minPrice, String maxPrice);
然后在com.daiyu.elastic.service.Impl.GoodsServiceImpl进行实现
@Override
public List<GoodsItemRep> queryByDateRange(String startTime, String endTime) {
List<GoodsItemRep> goodsItemReps = new ArrayList<>();
Query query = RangeQuery.of(q -> q
.field("updateTime")
.gt(JsonData.of(startTime))
.lt(JsonData.of(endTime))
.timeZone("Asia/Shanghai")
)._toQuery();
List<GoodsItem> result = client.search(index, GoodsItem.class, query);
result.stream().forEach(goodsItem -> {
GoodsItemRep goodsItemRep = new GoodsItemRep();
BeanUtils.copyProperties(goodsItem, goodsItemRep);
goodsItemReps.add(goodsItemRep);
});
return goodsItemReps;
}
@Override
public List<GoodsItemRep> queryByPriceRange(String minPrice, String maxPrice) {
List<GoodsItemRep> goodsItemReps = new ArrayList<>();
Query query = RangeQuery.of(q -> q
.field("basePrice")
.gt(JsonData.of(minPrice))
.lt(JsonData.of(maxPrice)))._toQuery();
List<GoodsItem> result = client.search(index, GoodsItem.class, query);
result.stream().forEach(goodsItem -> {
GoodsItemRep goodsItemRep = new GoodsItemRep();
BeanUtils.copyProperties(goodsItem, goodsItemRep);
goodsItemReps.add(goodsItemRep);
});
return goodsItemReps;
}
接下来在postman等接口调用工具进行调用查看接调用结果
- 日期范围查询
curl --location --request POST 'http://localhost:8089/goods/queryByDateRange?startDate=2008-06-01 00:00:00&endDate=2008-08-01 00:00:00'
- 价格范围查询
curl --location --request POST 'http://localhost:8089/goods/queryByPriceRange?minPrice=10.00&maxPrice=15.00'
到此我们已经熟悉了es的范围查询,更多的我们还需要根据自己的业务实际场景去调整。