弹性搜索中的多个过滤器和聚合

时间:2014-05-22 12:50:10

标签: elasticsearch

如何在elasticsearch中使用与聚合相关的过滤器?

官方文档仅提供filteraggregations的简单示例,并且没有对dsl进行正式描述 - 比较它,例如与postgres documentation

通过尝试我发现以下查询,弹性搜索接受了这个查询(没有解析错误),但忽略了给定的过滤器:

{
  "filter": {
    "and": [
      {
        "term": {
          "_type": "logs"
        }
      },
      {
        "term": {
          "dc": "eu-west-12"
        }
      },
      {
        "term": {
          "status": "204"
        }
      },
      {
        "range": {
          "@timestamp": {
            "from": 1398169707,
            "to": 1400761707
          }
        }
      }
    ]
  },
  "size": 0,
  "aggs": {
    "time_histo": {
      "date_histogram": {
        "field": "@timestamp",
        "interval": "1h"
      },
      "aggs": {
        "name": {
          "percentiles": {
            "field": "upstream_response_time",
            "percents": [
              98.0
            ]
          }
        }
      }
    }
  }
}

有人建议使用query代替filter。但官方文档通常建议the opposite过滤精确值。 query的另一个问题:虽然过滤器提供and,但query却没有。

有人可以指向文档,博客或书籍,它描述了编写非平凡的查询:至少是聚合加上多个过滤器。

4 个答案:

答案 0 :(得分:26)

我最终使用了filter aggregation - 未过滤的查询。所以现在我有3个嵌套的aggs元素。

由于http://www.elasticsearch.org/blog/all-about-elasticsearch-filter-bitsets/

,@ alex-brasetvik建议我使用bool过滤器代替and

我的最终实施:

{
  "aggs": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "_type": "logs"
              }
            },
            {
              "term": {
                "dc": "eu-west-12"
              }
            },
            {
              "term": {
                "status": "204"
              }
            },
            {
              "range": {
                "@timestamp": {
                  "from": 1398176502000,
                  "to": 1400768502000
                }
              }
            }
          ]
        }
      },
      "aggs": {
        "time_histo": {
          "date_histogram": {
            "field": "@timestamp",
            "interval": "1h"
          },
          "aggs": {
            "name": {
              "percentiles": {
                "field": "upstream_response_time",
                "percents": [
                  98.0
                ]
              }
            }
          }
        }
      }
    }
  },
  "size": 0
}

答案 1 :(得分:7)

将过滤器放入filtered - 查询。

顶级filter仅用于过滤搜索匹配,而不用于过滤/聚合。由于这种相当普遍的混淆,它在1.0中被重命名为post_filter

此外,您可能希望查看有关您经常要使用bool而不是and / or的原因的帖子:http://www.elasticsearch.org/blog/all-about-elasticsearch-filter-bitsets/

答案 2 :(得分:1)

更多关于@geekQ的答案:支持带空格字符的过滤字符串,对于多项术语搜索,请使用以下内容:

{   "aggs": {
    "aggresults": {
      "filter": {
        "bool": {
          "must": [
            {
              "match_phrase": {
                "term_1": "some text with space 1"
              }
            },
            {
              "match_phrase": {
                "term_2": "some text with also space 2"
              }
            }
          ]
        }
      },
      "aggs" : {
            "all_term_3s" : {
                "terms" : {
                    "field":"term_3.keyword",
                    "size" : 10000,
                    "order" : {
                        "_term" : "asc" 
                    }
                }
           }
        }
    }   },   "size": 0 }

答案 3 :(得分:0)

仅供参考,对于版本 7.2 ,我尝试使用以下方法来实现多个聚合过滤器:

POST movies/_search?size=0
{
  "size": 0,
  "aggs": {
    "test": {
      "filter": {
        "bool": {
          "must": {
            "term": {
              "genre": "action"
            }
          },
          "filter": {
            "range": {
              "year": {
                "gte": 1800,
                "lte": 3000
              }
            }
          }
        }
      },
      "aggs": {
        "year_hist": {
          "histogram": {
            "field": "year",
            "interval": 50
          }
        }
      }
    }
  }
}