理解elasticsearch的post_filter

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: elasticsearch的post_filter,是聚合查询时用到的参数,本机介绍了此参数的用法

欢迎访问我的GitHub

这里分类和汇总了欣宸的全部原创(含配套源码): https://github.com/zq2599/blog_demos

本篇概览

  • 《Elasticsearch 权威指南中,post_filter出现在聚合章节,描述post_filter的作用为:只过滤搜索结果,不过滤聚合结果;
  • 描述比较简单,还是用实例来加深理解吧。

环境信息

  • 以下是本次实例的环境信息,请确保您的Elasticsearch可以正常运行:
  1. 操作系统:Ubuntu 18.04.2 LTS
  2. JDK:1.8.0_191
  3. Elasticsearch:6.7.1
  4. Kibana:6.7.1

实例数据

  • 查询用到的数据是个名为cars的索引,里面保存了多条汽车销售记录,字段有品牌(make)、颜色(color)、价格(price)、售卖时间(sold)等,在elasticsearch-head查看数据如下图:

在这里插入图片描述

假设一个查询聚合的需求

  • 对上述索引,假设我们的查询需求是:品牌为ford的汽车有哪些颜色
  • 这个需求是容易实现的:先限定查询范围(品牌为ford),再用类型为terms的桶对color字段做聚合;
  • 具体的DSL怎么写呢?随着我们想要的数据的不同,有不同的写法:

第一种:用查询结果生成聚合结果,然后只返回聚合结果

  • 只要设置size参数为0,就不会返回查询结果(返回JSON中,hits.hits的数组长度为0):
GET /cars/transactions/_search
{
  "size": 0,
  "query": {                ---查询
    "bool": {               ---布尔查询
      "filter": {           ---用了过滤器
        "term": {           ---精确匹配
          "make": "ford"    ---匹配make字段为ford的文档
        }
      }
    }
  },
  "aggs": {
    "colors": {
      "terms": {           ---桶类型为terms
        "field": "color"   ---根据color字段聚合
      }
    }
  }
}
  • 返回内容中只有聚合结果:
{
  "took" : 144,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.0,
    "hits" : [ ]           ---这里面是查询结果,现在长度为0
  },
  "aggregations" : {       ---这里面是用前面的查询结果来做聚合的结果,所有品牌为ford的文档,根据颜色不同进入了两个桶
    "colors" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "blue",  ---蓝色
          "doc_count" : 1
        },
        {
          "key" : "green", ---绿色
          "doc_count" : 1
        }
      ]
    }
  }
}

第二种:用查询结果生成聚合结果,然后返回聚合结果和查询结果

  • 如果我们想在返回内容中包含查询结果,只要把"size": 0,这个参数去掉即可:
GET /cars/transactions/_search
{
  "query": {                ---查询
    "bool": {               ---布尔查询
      "filter": {           ---用了过滤器
        "term": {           ---精确匹配
          "make": "ford"    ---匹配make字段为ford的文档
        }
      }
    }
  },
  "aggs": {
    "colors": {
      "terms": {           ---桶类型为terms
        "field": "color"   ---根据color字段聚合
      }
    }
  }
}
  • 返回的内容如下所示,hits.hits的内容不再为空,而是包含了查询结果,至于聚合结果和前面是一样的:
{
  "took" : 39,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.0,
    "hits" : [                    ---这个JSON数组的每个元素,都一个品牌字段为ford的文档
      {
        "_index" : "cars",
        "_type" : "transactions",
        "_id" : "hVOQeGoBgL6DDzH6-9ay",
        "_score" : 0.0,
        "_source" : {
          "price" : 30000,
          "color" : "green",      ---颜色是green
          "make" : "ford",
          "sold" : "2014-05-18"
        }
      },
      {
        "_index" : "cars",
        "_type" : "transactions",
        "_id" : "ilOQeGoBgL6DDzH6-9ay",
        "_score" : 0.0,
        "_source" : {
          "price" : 25000,
          "color" : "blue",      ---颜色是blue
          "make" : "ford",
          "sold" : "2014-02-12"
        }
      }
    ]
  },
  "aggregations" : {
    "colors" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "blue",
          "doc_count" : 1
        },
        {
          "key" : "green",
          "doc_count" : 1
        }
      ]
    }
  }
}

第三种:用查询结果生成聚合结果,然后返回聚合结果和被再次过滤后的查询结果

  • 第三种返回的聚合结果与前面两种一模一样,都是品牌为ford的汽车的颜色;
  • 聚合结果生成完毕后,查询结果可以根据post_filter参数的设置而被再次过滤,例如品牌为ford的汽车,可以把其他颜色过滤掉,只要蓝色的,然后再返回,此时返回的查询结果中就只有品牌为ford并且颜色是blue的文档,具体的DSL如下:
GET /cars/transactions/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "make": "ford"
        }
      }
    }
  },
  "post_filter": {      ---在生成了聚合结果后,对即将返回的查询结果做一次过滤
    "term": {
      "color": "blue"   ---过滤条件是只保留color字段为blue的文档
    }
  },
  "aggs": {
    "colors": {
      "terms": {
        "field": "color"
      }
    }
  }
}
  • 返回数据如下,可见聚合结果和前面两种一模一样,只是查询结果中只有color字段为blue的文档:
{
  "took" : 13,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "cars",
        "_type" : "transactions",
        "_id" : "ilOQeGoBgL6DDzH6-9ay",
        "_score" : 0.0,
        "_source" : {
          "price" : 25000,
          "color" : "blue",
          "make" : "ford",
          "sold" : "2014-02-12"
        }
      }
    ]
  },
  "aggregations" : {
    "colors" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "blue",
          "doc_count" : 1
        },
        {
          "key" : "green",
          "doc_count" : 1
        }
      ]
    }
  }
}
  • 至此,post_filter的基本功能已介绍完毕,如果只做查询不做聚合,post_filter的作用和我们常用的filter是类似的,但由于post_filter是在查询之后才会执行,所以post_filter不具备filter对查询带来的好处(忽略评分、缓存等),因此,在普通的查询中不要用post_filter来替代filter;

欢迎关注阿里云开发者社区博客:程序员欣宸

学习路上,你不孤单,欣宸原创一路相伴...
相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
6月前
|
缓存 监控 索引
Elasticsearch中的post_filter后置过滤器技术
Elasticsearch中的post_filter后置过滤器技术
|
7月前
|
索引
说说 Elasticsearch filter 和 post_filter 的区别?
说说 Elasticsearch filter 和 post_filter 的区别?
64 0
|
25天前
|
存储 安全 数据管理
如何在 Rocky Linux 8 上安装和配置 Elasticsearch
本文详细介绍了在 Rocky Linux 8 上安装和配置 Elasticsearch 的步骤,包括添加仓库、安装 Elasticsearch、配置文件修改、设置内存和文件描述符、启动和验证 Elasticsearch,以及常见问题的解决方法。通过这些步骤,你可以快速搭建起这个强大的分布式搜索和分析引擎。
35 5
|
2月前
|
存储 JSON Java
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
这篇文章是关于Elasticsearch的学习指南,包括了解Elasticsearch、版本对应、安装运行Elasticsearch和Kibana、安装head插件和elasticsearch-ik分词器的步骤。
173 0
elasticsearch学习一:了解 ES,版本之间的对应。安装elasticsearch,kibana,head插件、elasticsearch-ik分词器。
|
3月前
|
NoSQL 关系型数据库 Redis
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
mall在linux环境下的部署(基于Docker容器),docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongodb、minio详细教程,拉取镜像、运行容器
mall在linux环境下的部署(基于Docker容器),Docker安装mysql、redis、nginx、rabbitmq、elasticsearch、logstash、kibana、mongo
|
4月前
|
数据可视化 Docker 容器
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
这篇文章提供了通过Docker安装Elasticsearch和Kibana的详细过程和图解,包括下载镜像、创建和启动容器、处理可能遇到的启动失败情况(如权限不足和配置文件错误)、测试Elasticsearch和Kibana的连接,以及解决空间不足的问题。文章还特别指出了配置文件中空格的重要性以及环境变量中字母大小写的问题。
一文教会你如何通过Docker安装elasticsearch和kibana 【详细过程+图解】
|
4月前
|
JSON 自然语言处理 数据库
Elasticsearch从入门到项目部署 安装 分词器 索引库操作
这篇文章详细介绍了Elasticsearch的基本概念、倒排索引原理、安装部署、IK分词器的使用,以及如何在Elasticsearch中进行索引库的CRUD操作,旨在帮助读者从入门到项目部署全面掌握Elasticsearch的使用。
|
4月前
|
Ubuntu Oracle Java
如何在 Ubuntu VPS 上安装 Elasticsearch
如何在 Ubuntu VPS 上安装 Elasticsearch
47 0
|
4月前
|
存储 Ubuntu Oracle
在Ubuntu 14.04上安装和配置Elasticsearch的方法
在Ubuntu 14.04上安装和配置Elasticsearch的方法
47 0
|
4月前
|
存储 安全 Java
在CentOS 7上安装和配置Elasticsearch的方法
在CentOS 7上安装和配置Elasticsearch的方法
283 0