08|过虑查询

80 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第15天,[点击查看活动详情]

01.过滤查询跟普通查询的区别

过滤查询跟普通查询基本类似,它们的主要区别是在评分机制和搜索行为上,因此性能也会有所差异。普通查询在搜索数据的时候会计算相关的评分相关性,会多一层计算的过程,而过滤查询没有,过滤查询只是判断这个文档是否匹配,如果匹配就返回"是",不匹配就是"否",没有计算相关性得分。

并且过滤查询查询数据的时候会先到缓存里面查有没有,如果有的话直接走缓存,速度比较快,没有的话会从磁盘取到匹配的数据,然后放到缓存。

过滤查询.png

02.ES的过滤查询

现在我们有这样一个场景,需要找出skuName包含字的文档,且日日期范围是2008-06-01 00:00:002008-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=巾'

调用结果

image-20221122233950923.png 至此过滤查询已经演示完毕