• ElasticSearch 2 (33)


    ElasticSearch 2 (33) - 信息聚合系列之聚合过滤

    摘要

    聚合范围限定还有一个自然的扩展就是过滤。因为聚合是在查询结果范围内操作的,任何可以适用于查询的过滤器也可以应用在聚合上。

    版本

    elasticsearch版本: elasticsearch-2.x

    内容

    聚合范围限定还有一个自然的扩展就是过滤。因为聚合是在查询结果范围内操作的,任何可以适用于查询的过滤器也可以应用在聚合上。

    Filtered 查询(Filtered Query)

    如果我们想找到售价在 $10,000 美元之上的所有汽车同时也为这些车计算平均售价,可以简单地使用一个 filtered 查询:

      GET /cars/transactions/_search
      {
          "size" : 0,
          "query" : {
              "filtered": {
                  "filter": {
                      "range": {
                          "price": {
                              "gte": 10000
                          }
                      }
                  }
              }
          },
          "aggs" : {
              "single_avg_price": {
                  "avg" : { "field" : "price" }
              }
          }
      }
    

    这正如我们在前面章节中讨论过那样,从根本上讲,使用 filtered 查询和使用 match 查询没有任何区别。查询(包括了一个过滤器)返回一组文档的子集,聚合正是操作这些文档。

    过滤桶(Filter Bucket)

    但是如果我们只想对聚合结果过滤怎么办?假设我们正在创建一个可以搜索汽车经销商的页面,我们希望显示用户搜索的结果,但是我们同时也想在页面上提供更丰富的信息,包括(与搜索匹配的)上个月度汽车的平均售价

    这里我们无法简单的做范围限定,因为有两个不同的条件。搜索结果必须是 ford,但是聚合结果必须满足 ford AND sold > now - 1M

    为了解决这个问题,我们可以用一种特殊的桶,叫做过滤桶。我们可以指定一个过滤桶,当文档满足过滤桶的条件时,我们将其加入到桶内。

    查询结果如下:

      GET /cars/transactions/_search
      {
         "size" : 0,
         "query":{
            "match": {
               "make": "ford"
            }
         },
         "aggs":{
            "recent_sales": {
               "filter": { #1
                  "range": {
                     "sold": {
                        "from": "now-1M"
                     }
                  }
               },
               "aggs": {
                  "average_price":{
                     "avg": {
                        "field": "price" #2
                     }
                  }
               }
            }
         }
      }
    

    #1 使用过滤桶在查询范围基础上应用过滤器。

    #2 avg 度量只会对 ford 和 一月以内售出 的文档计算平均售价。

    因为 filter 桶和其他桶的操作方式一样,所以可以随意将其他桶和度量嵌入其中。所有嵌套的组件都会 “继承” 这个过滤,这使我们可以按需针对聚合过滤出选择部分。

    展示过滤器(Post Filter)

    目前为止,我们可以同时对搜索结果和聚合结果进行过滤(一个 filtered 查询),以及针对聚合结果的一部分进行过滤(filter 桶)

    我们可能会想,“有只对搜索结果进行过滤而不过滤聚合结果的方式吗?”答案是使用 post_filter

    它是顶层搜索请求元素接收一个过滤器。这个过滤器在查询之后执行(这正是该过滤器的名字的由来:它在查询之后(post)执行)。正因为它在查询之后执行,它对查询范围没有任何影响,所以对聚合也不会有任何影响。

    我们可以利用这个行为对查询条件应用更多的过滤器,而不会影响其他的操作,就如 UI 上的各个分类面。让我们为汽车经销商设计另外一个搜索页面,这个页面允许用户搜索汽车同时可以根据颜色来过滤。颜色的选项是通过聚合获得的:

      GET /cars/transactions/_search
      {
          "size" : 0,
          "query": {
              "match": {
                  "make": "ford"
              }
          },
          "post_filter": {    #1
              "term" : {
                  "color" : "green"
              }
          },
          "aggs" : {
              "all_colors": {
                  "terms" : { "field" : "color" }
              }
          }
      }
    

    #1 post_filter 元素是顶层元素而且仅对命中结果进行过滤。

    查询部分找到所有的 ford 汽车,然后用 terms 聚合创建一个颜色列表。因为聚合对查询范围进行操作,颜色列表与福特汽车有的颜色相对应。

    最后,post_filter 会过滤搜索结果,只展示绿色福特汽车。这在查询执行过后发生,所以聚合不受影响。

    这通常对 UI 的连贯一致性很重要,可以想象用户在界面商选择了一类颜色(比如:green 绿色),期望的是搜索结果已经被过滤了,而不是过滤界面上的选项。如果我们应用 filtered 查询,界面会马上变成只显示 green 作为选项,这不是用户想要的!

    警告
    性能考虑(Performance consideration)

    只在我们需要区别过滤搜索结果和聚合结果时使用 post_filter,有时用户会在普通搜索使用 post_filter

    不要这么做!post_filter 的特性是在查询之后执行,所以任何过滤所带来的好处(比如缓存)都会完全失去。

    post_filter 应该只在我们需要不同过滤时,只与聚合一起使用。

    小结(Recap)

    选择合适类型的过滤(如:搜索命中、聚合或两者兼有)通常和我们期望如何表现用户交互有关。选择合适的过滤器(或组合)取决于我们期望如何将结果呈现给用户。

    • filtered 查询同时影响搜索结果和聚合结果。
    • filter 桶影响聚合。
    • post_filter 只影响搜索结果。

    参考

    elastic.co:
    Filtering Queries and Aggregations

  • 相关阅读:
    转:Swagger2自动生成接口文档和Mock模拟数据
    InfluxDB
    springboot application.properties文件加载顺序
    maven surefire插件与testng
    spring-boot项目学习路径
    collection 与stream与lambd表达式的结合使用
    转:Java中Lambda表达式的使用
    RPC之Thrift 介绍及java实例
    win10中shift+右键,在此处打开cmd窗口
    激活xmind的方法
  • 原文地址:https://www.cnblogs.com/richaaaard/p/5315990.html
Copyright © 2020-2023  润新知