【问题标题】:Elasticsearch: sort terms aggregation buckets by non-key columnElasticsearch:按非键列对术语聚合桶进行排序
【发布时间】:2020-09-02 22:02:30
【问题描述】:

数据

我在 ES 索引中保留了对象。它们每个都有一个 myKeymyName 字符串字段(保留为关键字字段)。对于同一个 myKey,不能保证 myName 总是相同的。例如。以下两个条目共享相同的 myKey,但具有不同的 myName 值:

{
  "myKey": "123asd",
  "myName": "United States",
  ...
},
{
  "myKey": "123asd",
  "myName": "United States of America",
  ...
},
{
  "myKey": "456fgh",
  "myName": "United Kingdom",
  ...
}

挑战

我需要选择并返回所有不同的 myKey 值,查找并显示最可能的 myName(在 myKey 的上下文中出现的次数最多) 并按 myName 对生成的存储桶进行排序。

到目前为止,我完成了以下工作:

  1. 使用 terms 聚合选择不同的 myKey 值。
  2. 使用 top_hits 聚合为每个 myKey 选择对应的第一个 myName 值。
  3. 使用术语聚合的 order 子句按 myKey 排序。

这是聚合的代码:

"aggs": {
"distinct": {
  "terms": {
    "field": "myKey",
    "order": {
      "_key": "desc"    <----- this sorts the buckets by myKey
    }
  },
  "aggs": {
    "tops": {
      "top_hits": {
        "size": 1,
        "_source": {
          "includes": ["myName"]
        }
      }
    }
  }
}

我阅读了ES documentation,解释了如何引入返回单个指标的第二个聚合。这似乎只针对数字字段。 myName 不是数字。

有没有办法按照 myName 对 ES 中的存储桶进行排序?

非常感谢任何帮助。

2020 年 9 月 2 日编辑

根据用户@joe的询问,目前和预期的结果如下。

当前结果

显然,桶的排序是基于键:123asd456fgh 之前:

"aggregations" : {
  "distinct" : {
    "buckets" : [
      {
        "key" : "123asd",
        "tops" : {
          "hits" : {
            "hits" : [
              {
                "_source" : {
                  "myName" : "United States"
                }
              }
            ]
          }
        }
      },
      {
        "key" : "456fgh",
        "tops" : {
          "hits" : {
            "hits" : [
              {
                "_source" : {
                  "myName" : "United Kingdom"
                }
              }
            ]
          }
        }
      }
    ]
  }
}

预期结果

任务是根据额外选择的字段 myName 对存储桶进行排序:United Kingdom 位于 United States 之前:

"aggregations" : {
  "distinct" : {
    "buckets" : [
      {
        "key" : "456fgh",
        "tops" : {
          "hits" : {
            "hits" : [
              {
                "_source" : {
                  "myName" : "United Kingdom"
                }
              }
            ]
          }
        }
      },
      {
        "key" : "123asd",
        "tops" : {
          "hits" : {
            "hits" : [
              {
                "_source" : {
                  "myName" : "United States"
                }
              }
            ]
          }
        }
      }
    ]
  }
}

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    通过_count:desc,您仅按字母顺序排列了顶部 agg...

    您是否尝试过以下在给定myKey 下查找最频繁的myNames 的方法?

    {
      "size": 0, 
      "aggs": {
        "by_key": {
          "terms": {
            "field": "myKey",
            "order": {
              "_key": "desc"
            }
          },
          "aggs": {
            "by_name": {
              "terms": {
                "field": "myName",
                "order":{
                  "_count": "desc"
                }
              }
            }
          }
        }
      }
    }
    

    或者您是否希望根据子 myNameagg 的结果对父 myKeyagg 进行排序?


    编辑

    通过多桶子聚合的结果对父 agg 进行排序会导致以下错误:

    桶只能在构建的子聚合器路径上排序 路径内的零个或多个单桶聚合和最终 路径末端的单桶或指标聚合。

    换句话说,你想要达到的目标是不可能的,这里是nicely explained why

    如果您的子聚合是数字(或单桶),它会是 possible

    目前,您唯一的选择似乎是在前端(或您使用这些 aggs 的任何地方)对当前响应进行后处理(或者更确切地说是后排序)。

    【讨论】:

    • 亲爱的@joe,我正在寻找后者:根据子myName agg 的结果对父myKey 进行排序。
    • 您能否提供所需的响应?我无法理解这种排序的行为方式。
    • 请查看编辑后的答案 - 当前和预​​期结果列表均已显示。感谢您抽出宝贵时间。
    • 这也是我的结论,但我认为我只是卡住了,必须有其他方法。我认为这是一个基本案例,用大多数其他系统(例如 SQL)解决是微不足道的,因此我很困惑地看到这是不可能的。
    • 对。如果您真的需要它,就像您定义的那样,几乎所有事情都可以使用脚本(更具体地说是 scripted_metrics)。看看我的其他一些帖子——也许你会在那里找到一些灵感:stackoverflow.com/…
    猜你喜欢
    • 2016-09-08
    • 2021-06-06
    • 2021-09-22
    • 2015-11-06
    • 2021-06-06
    • 2018-05-21
    • 2019-01-27
    • 1970-01-01
    • 2015-07-31
    相关资源
    最近更新 更多