Elasticsearch 多个聚合或术语和同一列上的聚合

Posted

技术标签:

【中文标题】Elasticsearch 多个聚合或术语和同一列上的聚合【英文标题】:Elasticsearch multiple aggregation or terms and aggregation on a same column 【发布时间】:2022-01-19 07:17:53 【问题描述】:

我想在 Elasticsearch 中实现 SQL 的功能。考虑下表:

我想要实现的是聚合列的不同值,SQL 等效:

select product,min(distinct price) from test group by product;

Expected output:

聚合可以是任何标准聚合,例如minmaxsumavgcount 等。

我已经尝试过使用无痛脚本,我可以通过无痛脚本实现所需的输出,但是以编程方式生成无痛脚本非常困难。

我正在寻找可以以编程方式生成的 EQL 查询或可以以编程方式生成无痛脚本的一些 java 插件。

Edit:

我试过的无痛脚本:


  "aggs": 
    "terms": 
      "scripted_metric": 
        "init_script": "state.rawMap = [:];",
        "map_script": "def product = doc['product'].value;state.rawMap.putIfAbsent(product, new ArrayList());def price = doc['price'].value;if(!state.rawMap.get(product).contains(price))state.rawMap.get(product).add(price);",
        "combine_script": "List outputList=new ArrayList();for (entry in state.rawMap.entrySet()) def map=[:]; def min=entry.getValue().get(0); for(price in entry.getValue())if(price<min)min=price;map.product=(entry.getKey()); map.min_price=min;outputList.add(map);return outputList;"
      
    
  

【问题讨论】:

你能展示你到目前为止尝试过的查询吗...我看不出这与简单的术语聚合+最小子聚合有什么不同...好奇... 我使用了无痛脚本。我无法使用 EQL 实现这一点。 请显示查询,否则我们在黑暗中拍摄 @Val 我已经添加了我尝试过的无痛脚本。 【参考方案1】:

无需无痛脚本!您想要的可以通过以下聚合查询来实现:


  "size": 0,
  "aggs": 
    "products": 
      "terms": 
        "field": "product"
      ,
      "aggs": 
        "distinct_price": 
          "terms": 
            "field": "price"
          ,
          "aggs": 
            "price_stats": 
              "stats": 
                "field": "price"
              
            
          
        
      
    
  

【讨论】:

感谢您的回答,如何找到价格的计数而不是最小值? 您可以使用stats 聚合,然后您就拥有了一切:最小值、最大值、计数等 上面的 EQL 不负责找出每个产品的不同价格。它考虑了所有的值。 它返回的结果与您的第二个屏幕截图完全相同 distinct 在这种情况下毫无意义:min(distinct price) 产生与 min(price) 相同的结果【参考方案2】:

以下查询将为您提供预期的结果:

POST test/_search

  "size": 0,
  "aggs": 
    "Fruites": 
      "terms": 
        "field": "product.keyword",
        "size": 10
      ,
      "aggs": 
        "min_price": 
          "min": 
            "field": "price"
          
        
      
    
  

样本结果:


  "took" : 3,
  "timed_out" : false,
  "_shards" : 
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  ,
  "hits" : 
    "total" : 
      "value" : 5,
      "relation" : "eq"
    ,
    "max_score" : null,
    "hits" : [ ]
  ,
  "aggregations" : 
    "Fruites" : 
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        
          "key" : "apple",
          "doc_count" : 2,
          "min_price" : 
            "value" : 120.0
          
        ,
        
          "key" : "pears",
          "doc_count" : 2,
          "min_price" : 
            "value" : 150.0
          
        ,
        
          "key" : "banana",
          "doc_count" : 1,
          "min_price" : 
            "value" : 70.0
          
        
      ]
    
  

您可以像下面这样创建索引映射:

PUT test

  "mappings": 
    "properties": 
      "price": 
        "type": "integer"
      ,
      "product": 
        "type": "text",
        "fields": 
          "keyword": 
            "type": "keyword",
            "ignore_above": 256
          
        
      
    
  

示例数据索引如下:

POST _bulk
"index":"_index":"test","_id":"1"
"product":"apple","price":"120"
"index":"_index":"test","_id":"2"
"product":"banana","price":"70"
"index":"_index":"test","_id":"3"
"product":"pears","price":"150"
"index":"_index":"test","_id":"4"
"product":"apple","price":"220"
"index":"_index":"test","_id":"5"
"product":"apple","price":"120"
"index":"_index":"test","_id":"5"
"product":"pears","price":"180"

【讨论】:

上面的 EQL 不负责找出每个产品的不同价格。它考虑了所有的值。

以上是关于Elasticsearch 多个聚合或术语和同一列上的聚合的主要内容,如果未能解决你的问题,请参考以下文章

Elasticsearch 术语或基数聚合 - 按不同值的数量排序

elasticsearch 多词重要词聚合

通过数组中的字符串聚合 Elasticsearch 术语

Elasticsearch:从聚合中的存储桶访问值

Elasticsearch 中的术语聚合返回单词而不是完整字段值的存储桶

elasticsearch - 聚合返回 key 中的术语,但不是完整的字段,我怎样才能返回完整的字段?