elasticsearch - 为什么需要过滤器聚合?

标签 elasticsearch elasticsearch-5

在使用elasticsearch (5.3.0) 时,我们在涉及一些嵌套聚合的查询中遇到了内存不足问题。

我们凭经验发现问题在于聚合是在完整索引上计算的,而不是考虑 query block 中指定的条件。后来我们设法运行查询,将这些条件移动到包装所有原始聚合的 filter 聚合中(请参阅 docs )。

为什么有一个单独的语法?如果elasticsearch在填充存储桶时简单地考虑所有查询条件不是更好吗?

如果我选择以这种方式将所有聚合查询包装在 filter 查询中,会有哪些风险和/或限制?逻辑上有什么不同吗?

注意:在我们的应用程序中,我们根本不关心文档评分。所有条件的唯一目的是过滤文档,而不是对其进行排序。我们确实根据文档计数或聚合指标来过滤存储桶。

编辑:有些人提出了疑问,这里是为了帮助澄清情况。请注意,这个问题是一般性的,针对此特定案例。

{
  "query": {
    // we did try a filtering rather than a query with the same results
    "term": {
      "urlpath": "some_url_path.html"
    }
  },
  "aggs": {
    "agg_1": {
      "terms": {
        "size": 10,
        "order": {
          "sessions_number": "desc"
        },
        "field": "urlpath"
      },
      "aggs": {
        "sessions_number": {
          "cardinality": {
            "field": "session"
          }
        }
      }
    }
  }
}

及之后:

{
  "aggs": {
    "agg_0": {
      "filter": {
        "term": {
          "urlpath": "some_url_path.html"
        }
      },
      "aggs": {
        "agg_1": {
          "terms": {
            "size": 10,
            "order": {
              "sessions_number": "desc"
            },
            "field": "urlpath"
          },
          "aggs": {
            "sessions_number": {
              "cardinality": {
                "field": "session"
              }
            }
          }
        }
      }
    }
  }
}

编辑2:我尝试使用过滤器查询,如下面@Lusid的建议,但遇到了同样的问题。

注意2:如果删除 order 子句,就不会出现此问题,对于过滤器而不是查询也是如此。这对我们来说是最令人惊讶的,因为应该只有一个存储桶,使得任何订购都变得微不足道。这让我相信过滤没有在分桶之前发生,因此我尝试将所有内容包装在过滤聚合中。

最佳答案

在第一个示例中,您实际上并没有过滤数据,而是查询数据。这仅影响搜索结果的评分过程,而不影响聚合的过滤。

尽管 ElasticSearch 的最新版本已经结合了查询/过滤语法,但理解两者之间的区别仍然很重要。根据此处的文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html

A query clause used in query context answers the question “How well does this document match this query clause?” Besides deciding whether or not the document matches, the query clause also calculates a _score representing how well the document matches, relative to other documents.

In filter context, a query clause answers the question “Does this document match this query clause?” The answer is a simple Yes or No — no scores are calculated. Filter context is mostly used for filtering structured data, e.g.

构建第一个查询的更好方法是将过滤器包装在 query.boolquery.constant_score 中,如下所示:

{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "urlpath": "some_url_path.html"
        }
      }
    }
  },
  "aggs": {
    "agg_1": {
      "terms": {
        "size": 10,
        "order": {
          "sessions_number": "desc"
        },
        "field": "urlpath"
      },
      "aggs": {
        "sessions_number": {
          "cardinality": {
            "field": "session"
          }
        }
      }
    }
  }
}

有关这两个选项的更多信息:

恒定分数查询: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html

bool 查询(过滤器部分): https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

当然,拥有这两个选项的优点是您可以对整个搜索应用整体过滤器,然后进一步过滤聚合。

希望这有帮助!

编辑:我主要是解决过滤器背后的原因,因为它在查询中使用,所以过滤器没有按照您期望的方式运行。至于内存问题,你确定这里没有引发组合爆炸吗?您可以尝试将宽度优先的收集模式添加到顶级聚合中?有关组合爆炸的更多信息:https://www.elastic.co/guide/en/elasticsearch/guide/current/_preventing_combinatorial_explosions.html

试试这个:

{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "urlpath": "some_url_path.html"
        }
      }
    }
  },
  "aggs": {
    "agg_1": {
      "terms": {
        "size": 10,
        "order": {
          "sessions_number": "desc"
        },
        "field": "urlpath",
        "collect_mode": "breadth_first"
      },
      "aggs": {
        "sessions_number": {
          "cardinality": {
            "field": "session"
          }
        }
      }
    }
  }
}

关于elasticsearch - 为什么需要过滤器聚合?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43344058/

相关文章:

elasticsearch - 嵌套类型上的Elasticsearch通配符查询

elasticsearch - Elasticsearch甚至在5-6秒后仍提供缓存的结果

elasticsearch - 日期汇总-ElasticSearch

elasticsearch - Microsoft Power BI 和 ElasticSearch

elasticsearch - 如何在Heroku Cedar Stack上使用ElasticSearch&Tire获得Rails 3.1?

elasticsearch - Elasticsearch 中的词根替换原始字符串

elasticsearch - 无法在ELK 5.4上正确解析timetstamp

elasticsearch - 是否可以通过Elasticsearch中的映射来更新索引中的现有字段?

elasticsearch - 匹配无效的 Elasticsearch 日期范围

elasticsearch - elasticsearch:基于变量的值增强查询