【问题标题】:Elasticsearch aggregation on a field with dynamic properties具有动态属性的字段上的 Elasticsearch 聚合
【发布时间】:2021-05-29 05:26:45
【问题描述】:

鉴于以下映射,其中变体是 nested 类型,选项是 flattened 类型:

{
  "doc_type" : "product",
  "id" : 1,
  "variants" : [
    {
      "options" : {
        "Size" : "XS",
      },
      "price" : 1,
    },

    {
      "options" : {
        "Size" : "S",
        "Material": "Wool"
      },
      "price" : 6.99,
    },
  ]
} 

我想运行一个聚合,生成以下格式的数据:

{
  "variants.options.Size": {
    "buckets" : [
      {
        "key" : "XS",
        "doc_count" : 1
      },
      {
        "key" : "S",
        "doc_count" : 1
      },
    ],
  },
  "variants.options.Material": {
    "buckets" : [
      {
        "key" : "Wool",
        "doc_count" : 1
      }
    ],
  },
} 

我可以很容易地做这样的事情:

"aggs": {
    "variants.options.Size": {
      "terms": {
        "field": "variants.options.Size"
      }
    },
    "variants.options.Material": {
      "terms": {
        "field": "variants.options.Material"
      }
    }
  }

这里需要注意的是,我们使用flattened 类型作为选项,因为选项中的字段是动态的,所以我无法事先知道我们想要聚合在SizeMaterial

本质上,我想告诉 Elasticsearch 它应该聚合它在options 下找到的任何键。有没有办法做到这一点?

【问题讨论】:

    标签: elasticsearch kibana elastic-stack elasticsearch-aggregation


    【解决方案1】:

    我想告诉 Elasticsearch 它应该聚合它在选项下找到的任何键。有没有办法做到这一点?

    不直接。不久前我有the same question。到目前为止,我还没有找到一个干净的解决方案,我确信没有。

    幸运的是,有一个scripted_metric 解决方法I outlined here。将其应用于您的用例:

    POST your_index/_search
    {
      "size": 0,
      "aggs": {
        "dynamic_variant_options": {
          "scripted_metric": {
            "init_script": "state.buckets = [:];",
            "map_script": """
              def variants = params._source['variants'];
              for (def variant : variants) {
                for (def entry : variant['options'].entrySet()) {
                  def key = entry.getKey();
                  def value = entry.getValue();
                  def path = "variants.options." + key;
    
                  if (state.buckets.containsKey(path)) {
                    if (state.buckets[path].containsKey(value)) {
                      state.buckets[path][value] += 1;
                    } else {
                      state.buckets[path][value] = 1;
                    }
                  } else {
                    state.buckets[path] = [value:1];
                  }
                }
              }
            """,
            "combine_script": "return state",
            "reduce_script": "return states"
          }
        }
      }
    }
    

    会产生:

    "aggregations" : {
      "dynamic_variant_options" : {
        "value" : [
          {
            "buckets" : {
              "variants.options.Size" : {
                "S" : 1,
                "XS" : 1
              },
              "variants.options.Material" : {
                "Wool" : 1
              }
            }
          }
        ]
      }
    }
    

    如果您希望 buckets 成为 key-doc_count 对的数组,而不是像我的示例中那样的哈希映射,则需要调整 painless 代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-08
      • 2021-07-23
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 2016-05-20
      • 2014-08-24
      相关资源
      最近更新 更多