具有动态数据/嵌套对象的聚合

8gsdolmq  于 2021-06-15  发布在  ElasticSearch
关注(0)|答案(1)|浏览(399)

我试图在elasticsearch中聚合动态Map的字段。
例如:

POST test/_doc/1
{
    "settings": {
        "range": {
            "value": 200,
            "display": "200 km"
        },
        "transmitter": {
            "value": 1.2,
            "display": "1.2 Ghz"
        }
    }
}

下的属性 settings 是动态的。基本上我需要这样一个查询:

{
    "size": 0,
    "query": {
        "match_all": {}
    },
    "aggs": {
        "settings": {
            "terms": {
                "field": "settings.*.display"
            }
        }
    }
}

* 在这里不起作用,我想知道是否有一种方法可以从无痛脚本返回字段,然后使用管道聚合?我找不到无痛的 Object.keys(settings) 在javascript中。
我见过一种嵌套对象的方法,但我想避免这种情况,因为可能有许多“设置”属性,默认限制是50,而嵌套对象有10000个属性。

watbbzwu

watbbzwu1#

无痛的相当于 Object.keys().keySet() . 可以在脚本化度量agg中实现以下迭代逻辑:

GET test/_search
{
  "size": 0,
  "aggs": {
    "dynamic_fields_agg": {
      "scripted_metric": {
        "init_script": "state.map = [:];",
        "map_script": """
          def source = params._source['settings'];
            for (def key : source.keySet()) {
              if (source[key].containsKey("display")) {
                 if (state.map.containsKey(key)) { 
                  state.map[key].add(source[key].display);
                 } else {
                   state.map[key] = [source[key].display];
                 }
              }
            }
        """,
        "combine_script": "return state",
        "reduce_script": "return states"
      }
    }
  }
}

会产生类似

{
  "aggregations":{
    "dynamic_fields_agg":{
      "value":[
        {
          "map":{
            "range":[
              "200 km"
            ],
            "transmitter":[
              "1.2 Ghz"
            ]
          }
        }
      ]
    }
  }
}

现在您可以随心所欲地对reduce/combine脚本中的值进行后期处理。
在这里使用嵌套字段不会给您带来太多好处——在这里也不允许使用通配符路径。前段时间我自己也问过。
更新--内联版本:

GET /test/_search
{  "size": 0,  "aggs": {    "dynamic_fields_agg": {      "scripted_metric": {        "init_script": "state.map = [:];",        "map_script": "          def source = params._source[\"settings\"];\n            for (def key : source.keySet()) {\n              if (source[key].containsKey(\"display\")) {\n                 if (state.map.containsKey(key)) { \n                  state.map[key].add(source[key].display);\n                 } else {\n                   state.map[key] = [source[key].display];\n                 }\n              }\n            }",        "combine_script": "return state",        "reduce_script": "return states"      }    }  }}

相关问题