开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,[点击查看活动详情]
01.过滤查询跟普通查询的区别
过滤查询跟普通查询基本类似,它们的主要区别是在评分机制和搜索行为上,因此性能也会有所差异。普通查询在搜索数据的时候会计算相关的评分相关性,会多一层计算的过程,而过滤查询没有,过滤查询只是判断这个文档是否匹配,如果匹配就返回"是",不匹配就是"否",没有计算相关性得分。
并且过滤查询查询数据的时候会先到缓存里面查有没有,如果有的话直接走缓存,速度比较快,没有的话会从磁盘取到匹配的数据,然后放到缓存。
02.ES的过滤查询
现在我们有这样一个场景,需要找出skuName包含巾字的文档,且日日期范围是2008-06-01 00:00:00到2008-08-01 00:00:00
在kibana用DSL命令如下
GET /goods_item_index/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"updateTime": {
"gte": "2008-06-01 00:00:00",
"lte": "2008-08-01 00:00:00",
"time_zone": "Asia/Shanghai"
}
}
}
],
"filter": [
{
"term": {
"skuName": "巾"
}
}
]
}
}
}
-
must表示进行日期范围内的查询,并进行相关度评分 -
filter表示对结果进行过滤,找出包含巾的文档
3.基于Java API实现
我们在service创建filter查询接口
1
/**
2
* 过滤查询
3
*
4
* @param startTime 开始时间
5
* @param endTime 结束时间
6
* @param skuName skuName
7
* @return 返回结果集
8
*/
9
List<GoodsItemRep> queryFilter(String startTime, String endTime, String skuName);
实现类
@Override
public List<GoodsItemRep> queryFilter(String startTime, String endTime,String skuName) {
List<GoodsItemRep> goodsItemReps = new ArrayList<>();
//范围查询
Query rangeQuery = RangeQuery.of(q -> q
.field("updateTime")
.gt(JsonData.of(startTime))
.lt(JsonData.of(endTime))
.timeZone("Asia/Shanghai"))._toQuery();
//term查询
Query termQuery = TermQuery.of(t -> t.
field("skuName")
.value(skuName))._toQuery();
//查询条件组合
Query query = BoolQuery.of(b -> b
.must(rangeQuery)
.filter(termQuery)
)._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/queryFilter?startDate=2008-06-01 00:00:00&endDate=2008-08-01 00:00:00&skuName=巾'
调用结果