参考文章:Es检索 must与filter区别

must和filter使用场景

  1. 先使用filter把不需要的过滤掉,例如现在有一个电子商务的网站,我要查询一个category的id为1下面的所有产品,那么我首先会使用filter把category id等于1的产品过滤出来,也就是查出来
  2. 对于上面的filter出来的结果我再这个category下面查询name为“五子弥勒”的产品,这个时候我就会使用query,为什么呢,因为可能有的产品的name完全match 这个“五子弥勒”的关键字,但是有的产品可能只会match其中的一个词汇,所以,如果我需要把有相似性的查出来,这个是query是具备这个功能的,query的本质不是筛选,而是查询。query他会给结果打分,然后按照分数进行一个排序,如果命中的比较多,分数自然就很高,那么就会排在前面。这里提到了一个打分的概念,个人认为这个打分主要还是看分词器对他的命中,然后给一个评估,关于分词器,我会在后面的博客中提到。

所以,这个时候,大家应该知道filter和query的主要区别了,另外关于性能的我在提一下,上面提到 filter 是不进行打分的,他只是一个筛选,对不感兴趣的直接筛选掉;而query需要打分,可以想象成是一个命中率的概念,是一个率,不过如果你不想看到打分,你可以通过参数去控制,结果也就没有排序了,但是实际上,对性能的提升不大,因为主要的性能不是放在排序上面,而是在匹配上面

例子 

//组合查询对象,
//如搜索条件为“小米手机”这里must会分词为“小米”和“手机”这两个词是or关系
//加operator(Operator.AND)可以把or改为and关系
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
boolQueryBuilder.must(QueryBuilders.matchQuery("name",searchmap.get("keywords")).operator(Operator.AND));
 
//组合查询对象
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//filter指不分词查询
boolQueryBuilder.filter(QueryBuilders.termQuery("brandName",searchmap.get("brand")));

DSL: Elasticsearch支持很多查询方式,其中一种就是DSL,它是把请求写在JSON里面,然后进行相关的查询。 

举个DSL例子:

GET _search
{
  "query": { 
    "bool": { 
      "must": [
        { "match": { "title":   "Search"        }}, 
        { "match": { "content": "Elasticsearch" }}  
      ],
      "filter": [ 
        { "term":  { "status": "published" }}, 
        { "range": { "publish_date": { "gte": "2015-01-01" }}} 
      ]
    }
  }
}

查询的种类

Elasticsearch中的DSL主要由两部分组成:

Leaf query Cluase 暂且叫做叶查询子句吧

这种查询可以单独使用,针对某一特定的字段查询特定的值,比如match、term、range等

Compound query Cluase复合查询子句

这种查询配合其他的叶查询或者复合查询,用于在逻辑上,组成更为复杂的查询,比如bool

查询虽然包含这两种,但是查询在不同的执行环境下,操作还是不一样的。

Query与Filter

查询在Query查询上下文和Filter过滤器上下文中,执行的操作是不一样的:

查询上下文:

在查询上下文中,查询会回答这个问题——“这个文档匹不匹配这个查询,它的相关度高么?”

如何验证匹配很好理解,如何计算相关度呢?之前说过,ES中索引的数据都会存储一个_score分值,分值越高就代表越匹配。另外关于某个搜索的分值计算还是很复杂的,因此也需要一定的时间。

查询上下文 是在 使用query进行查询时的执行环境,比如使用search的时候。

过滤器上下文:

在过滤器上下文中,查询会回答这个问题——“这个文档匹不匹配?”

答案很简单,是或者不是。它不会去计算任何分值,也不会关心返回的排序问题,因此效率会高一点。

过滤上下文 是在使用filter参数时候的执行环境,比如在bool查询中使用Must_not或者filter

另外,经常使用过滤器,ES会自动的缓存过滤器的内容,这对于查询来说,会提高很多性能。

总结

1 查询上下文中,查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;在过滤器上下文中,查询操作仅判断是否满足查询条件

2 过滤器上下文中,查询的结果可以被缓存。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐