聚合结果的 Elasticsearch 过滤器(用于搜索和聚合)

Posted

技术标签:

【中文标题】聚合结果的 Elasticsearch 过滤器(用于搜索和聚合)【英文标题】:Elasticsearch filter on aggregation result (for search and aggregation) 【发布时间】:2020-02-06 23:31:43 【问题描述】:

这个问题的一部分与:Elasticsearch filter on aggregation

上下文

假设我的 Elasticsearch 索引包含一些订单。每个订单都有一个字段价格和一个字段金额。这导致索引如下所示:

[
  
    "docKey": "order01",
    "user": "1",
    "price": 8,
    "amount": 20
  ,
  
    "docKey": "order02",
    "user": "1",
    "price": 14,
    "amount": 3
  ,
  
    "docKey": "order03",
    "user": "2",
    "price": 5,
    "amount": 1
  ,
  
    "docKey": "order04",
    "user": "2",
    "price": 10,
    "amount": 3
  
]

我想做的事

我想要做的是过滤每个用户聚合的一些值。我想为搜索做这种过滤器,也为了对其应用聚合。例如,在此示例中,我想检索所有用户的文档,这些用户的平均订单价格在 9-14 范围内。

用户 1 的平均价格订单为 11,因此我们保留了他的两个订单。 用户 2 的平均价格订单为 7.5,因此他的两个订单都没有保留。

这是最简单的部分。在我过滤后只获得用户一个。我想对结果进行更多聚合。

因此,例如:我希望在桶 [0,10] 和 [10,20] 中为所有平均订单价格在 9 -14.

除了这个问题,我的答案是桶[0,10]中的0和桶[10,20]中的一个(仅保留用户1,因为他的平均价格。他的平均金额是11.5所以在桶 [10,20])。

我的尝试

我已设法对过滤器进行操作,以检索平均订单价格在 9-14 范围内的用户。我通过首先对用户提交的术语进行聚合来做到这一点。然后我做了一个子聚合,它是价格的平均聚合。然后我做一个桶选择器管道聚合,检查之前计算的平均价格是否在 9 到 14 之间。

我还设法进行了我想要的聚合,但没有使用以前的过滤器。我为每个范围的过滤器做了完全相同的事情。然后我统计每个桶的结果数。

我没有找到任何方法对存储桶选择器结果应用其他聚合。所以我不能先做过滤器然后应用范围......

此外,这些解决方案并不优雅。我认为它们不会扩大规模,因为文档的很大一部分需要在答案中返回并进一步处理(即使它不在互联网上,我更愿意避免这样做,我聚合的结果大小可能会受到限制?)。

【问题讨论】:

【参考方案1】:

我设法找到了一个解决方案,但它并不优雅,并且可能难以扩展。

对用户进行术语聚合。 作为术语聚合的子聚合,执行计算平均价格的平均聚合。

作为术语聚合的子聚合,执行平均聚合以计算金额的平均值。

执行桶选择器管道聚合,过滤以仅将 avg_price 保持在 [9-14] 范围内。

执行桶选择器管道聚合,过滤以仅将 avg_amount 保持在 [0-10] 中 执行“计数”存储桶脚本管道聚合(脚本返回一个)。 对计数进行求和的桶和管道聚合。 对所需的所有范围([0-10]、[10-20])重复所有步骤

【讨论】:

复杂的我不知道...但肯定不理想。你有更好的解决方案吗?

以上是关于聚合结果的 Elasticsearch 过滤器(用于搜索和聚合)的主要内容,如果未能解决你的问题,请参考以下文章

elasticSearch - 高级检索

理解elasticsearch的post_filter

ElasticSearch聚合分析

Elasticsearch:随机采样器聚合 - Random sampler aggregation

Elasticsearch 学习之子聚集过滤

从聚合结果中过滤空桶