【问题标题】:Stats Aggregation with Min Mode in ElasticSearch在 ElasticSearch 中使用 Min 模式进行统计信息聚合
【发布时间】:2021-03-01 12:33:51
【问题描述】:

我在 ElasticSearch 中有以下映射

{
       "properties":{
          "Costs":{
             "type":"nested",
             "properties":{
                "price":{
                   "type":"integer"
                }
             }
          }
       }
    }

所以每个文档都有一个数组字段 Costs,其中包含许多元素,每个元素都有价格。我想找到最低和最高价格,条件是 - 从每个数组中应该考虑最低价格的元素。所以它基本上是每个数组的最小值中的最小值/最大值。

假设我有 2 个成本字段为的文档

Costs: [
 {
  "price": 100,
 },
 {
  "price": 200,
 }
]

Costs: [
 {
  "price": 300,
 },
 {
  "price": 400,
 }
]

所以我需要找到统计数据 这是我目前使用的查询

{
   "costs_stats":{
      "nested":{
         "path":"Costs"
      },
      "aggs":{
         "price_stats_new":{
            "stats":{
               "field":"Costs.price"
            }
         }
      }
   }
}

它给了我这个:

"min" : 100,
"max" : 400

但我需要在考虑每个数组的最小元素后找到统计信息。 所以这就是我需要的:

"min" : 100,
"max" : 300

就像我们在排序中有一个“模式”选项一样,统计数据聚合中是否也有类似的东西,或者任何其他实现这一点的方法,可能使用脚本或其他东西。请建议。我真的被困在这里了。

如果有什么需要请告诉我

更新 1:

查询最小值/最大值

{
   "_source":false,
   "timeout":"5s",
   "from":0,
   "size":0,
   "aggs":{
      "price_1":{
         "terms":{
            "field":"id"
         },
         "aggs":{
            "price_2":{
               "nested":{
                  "path":"Costs"
               },
               "aggs":{
                  "filtered":{
                     "aggs":{
                        "price_3":{
                           "min":{
                              "field":"Costs.price"
                           }
                        }
                     },
                     "filter":{
                        "bool":{
                           "filter":{
                              "range":{
                                 "Costs.price":{
                                    "gte":100
                                 }
                              }
                           }
                        }
                     }
                  }
               }
            }
         }
      },
      "minValue":{
         "min_bucket":{
            "buckets_path":"price_1>price_2>filtered>price_3"
         }
      }
   }
}

只有几个桶来了,因此最小/最大值在其中,这是不正确的。有大小限制吗?

【问题讨论】:

    标签: elasticsearch elastic-stack elasticsearch-aggregation elasticsearch-dsl


    【解决方案1】:

    实现您的用例的一种方法是在每个文档中再添加一个字段id。借助 id 字段 terms aggregation 可以执行,因此桶将被动态构建 - 每个唯一值一个。

    然后,我们可以申请min aggregation,它将返回从聚合文档中提取的数值中的最小值。

    添加一个包含索引数据、映射、搜索查询和搜索结果的工作示例

    索引映射:

    {
      "mappings": {
        "properties": {
          "Costs": {
            "type": "nested"
          }
        }
      }
    }
    

    索引数据:

    {
      "id":1,
      "Costs": [
        {
          "price": 100
        },
        {
          "price": 200
        }
      ]
    }
    {
      "id":2,
      "Costs": [
        {
          "price": 300
        },
        {
          "price": 400
        }
      ]
    }
    

    搜索查询:

    {
        "size": 0,
        "aggs": {
            "id_terms": {
                "terms": {
                    "field": "id",
                    "size": 15              <-- note this
                },
                "aggs": {
                    "nested_entries": {
                        "nested": {
                            "path": "Costs"
                        },
                        "aggs": {
                            "min_position": {
                                "min": {
                                    "field": "Costs.price"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    搜索结果:

    "aggregations": {
        "id_terms": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": 1,
              "doc_count": 1,
              "nested_entries": {
                "doc_count": 2,
                "min_position": {
                  "value": 100.0
                }
              }
            },
            {
              "key": 2,
              "doc_count": 1,
              "nested_entries": {
                "doc_count": 2,
                "min_position": {
                  "value": 300.0
                }
              }
            }
          ]
        }
    

    也可以使用 stats 聚合来实现(如果您再添加一个字段 id 来唯一标识您的文档)

    {
      "size": 0,
      "aggs": {
        "id_terms": {
          "terms": {
            "field": "id",
            "size": 15              <-- note this
          },
          "aggs": {
            "costs_stats": {
              "nested": {
                "path": "Costs"
              },
              "aggs": {
                "price_stats_new": {
                  "stats": {
                    "field": "Costs.price"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    更新 1:

    要在这些最小值中找到最大值(如上述查询所示),您可以使用max bucket aggregation

    {
      "size": 0,
      "aggs": {
        "id_terms": {
          "terms": {
            "field": "id",
            "size": 15         <-- note this
          },
          "aggs": {
            "nested_entries": {
              "nested": {
                "path": "Costs"
              },
              "aggs": {
                "min_position": {
                  "min": {
                    "field": "Costs.price"
                  }
                }
              }
            }
          }
        },
        "maxValue": {
          "max_bucket": {
            "buckets_path": "id_terms>nested_entries>min_position"
          }
        }
      }
    }
    

    搜索结果:

    "aggregations": {
        "id_terms": {
          "doc_count_error_upper_bound": 0,
          "sum_other_doc_count": 0,
          "buckets": [
            {
              "key": 1,
              "doc_count": 1,
              "nested_entries": {
                "doc_count": 2,
                "min_position": {
                  "value": 100.0
                }
              }
            },
            {
              "key": 2,
              "doc_count": 1,
              "nested_entries": {
                "doc_count": 2,
                "min_position": {
                  "value": 300.0
                }
              }
            }
          ]
        },
        "maxValue": {
          "value": 300.0,
          "keys": [
            "2"
          ]
        }
      }
    

    【讨论】:

    • @user11037262 你有机会看我的回答吗,期待得到你的反馈:)
    • 嘿,谢谢你的回答,你的方法是计算每个文件的最低价格。但是为了获得这些最小值中的最大值,我必须在我的应用程序代码中再次对它们进行排序。无论如何,要从 ES 查询本身获得这些最小值中的最小值/最大值。
    • @user11037262 是的,您可以在这些最小值中找到最小值/最大值。请仔细阅读我更新的答案,如果这能解决您的问题,请告诉我?
    • 通过它,看起来这应该可以工作。完成查询后将在此处更新。
    • 我遇到了一个问题,在为 min_position aggs 创建存储桶时,只创建了几个存储桶。我有一个用于数组元素的附加过滤器。用我的查询更新问题。请检查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-12
    • 2012-10-01
    • 1970-01-01
    相关资源
    最近更新 更多