【问题标题】:ElasticSearch Aggregations: subtracting aggregations based upon matchElasticSearch Aggregations:根据匹配减去聚合
【发布时间】:2014-04-14 15:38:34
【问题描述】:

使用一个简单但有些人为的例子,假设我在 ElasticSearch 中存储了几个库存文档,其中每个文档代表购买或销售商品:

[
{item_id: "foobar", type: "cost", value: 12.34, timestamp:149382734621},
{item_id: "bizbaz", type: "sale", value: 45.12, timestamp:149383464621},
{item_id: "foobar", type: "sale", value: 32.74, timestamp:149384824621},
{item_id: "foobar", type: "cost", value: 12.34, timestamp:149387435621},
{item_id: "bizbaz", type: "sale", value: 45.12, timestamp:149388434621},
{item_id: "bizbaz", type: "cost", value: 41.23, timestamp:149389424621},
{item_id: "foobar", type: "sale", value: 32.74, timestamp:149389914621},
{item_id: "waahoo", type: "sale", value: 11.23, timestamp:149389914621},
...
]

在指定的时间范围内,我想计算每个项目的当前利润。所以例如我想返回:

foobar_profit = sum(value of all documents item_id="foobar" and type="sale")
               -sum(value of all documents item_id="foobar" and type="cost")
bizbaz_profit = sum(value of all documents item_id="bizbaz" and type="sale")
               -sum(value of all documents item_id="bizbaz" and type="cost")
...

有两个方面我还不明白如何实现。

  1. 我知道如何aggregate over terms,所以这将允许我对所有“foobar”项目的值求和,而不管类型如何。 但我不知道如何对两个字段匹配的所有文档求和。例如,我想在复合键 (item_id,type) 上聚合上述数据集。然后上面的数据集将产生聚合:

    • (foobar,cost)->24.68
    • (foobar,sale)->65.48
    • (商务,成本)->41.23
    • (bizbaz,sale)->90.24
    • (waahoo,sale)->11.23
  2. 假设我可以做到 #1,我将拥有像 foobar_costfoobar_sale 这样的聚合。但我不知道如何组合两个聚合,以便在这种情况下foobar_profit = foobar_sale - foobar_cost。所以上面的聚合会变成

    • foobar_profit->40.8
    • bizbaz_profit->49.01
    • waahoo_profit->11.23

一些最后的笔记:

  • 在上面的示例中,我只列出了 3 个 item_id,但考虑到会有数千个 item_id,所以我不能对每个 item_id 进行特殊情况查询。
  • 另外,对于特定商品,costsale 商品将在不同的时间出现,因此我们不能将成本和销售价格放在同一个文档中并区分字段。
  • 我可以发回所有数据并执行聚合客户端的最后一步,但这可能是大量数据。真的,如果可能的话,我需要在服务器端执行此操作,以便我可以按 profit 对结果进行排序并返回前 N 个。

【问题讨论】:

    标签: elasticsearch analytics aggregate


    【解决方案1】:

    您可以只使用嵌套聚合。有关工作示例,请参见此处:https://gist.github.com/mattweber/71033b1bf2ebed1afd8e

    我在这个例子中使用了 MatchAll Query,但你可以用 RangeQuery 或任何你需要的东西来替换它。

    【讨论】:

    • 哦,如果你想看到一些真正的力量,你可以使用顶级 DateHistogram Aggregation 来为你计算日期范围! elasticsearch.org/guide/en/elasticsearch/reference/current/…
    • 感谢您的示例,尽管我想要的只是比这更复杂的一步。我已经更新了我的示例以阐明我的目标(从“我尚不了解如何实现的两个方面”开始,然后向下)。
    • 顺便说一句,自从我在一家新公司开始工作以来,我终于能够深入研究 ES ......真的很漂亮。 :-)
    • 好的,我的答案涵盖#1。我不确定 #2 是否可行,让我考虑一下。
    • 我不认为#2 目前是可能的,但可能是我们可以添加的东西。我在github.com/elasticsearch/elasticsearch/issues/5923 上打开了一个问题来跟踪这个问题。
    猜你喜欢
    • 1970-01-01
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多