You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Elasticsearch嵌套聚合条件路径:按评分聚合仅取IP或InstanceId

解决嵌套字段聚合时仅保留IP/InstanceId其中一个的问题

嘿,我完全懂你遇到的这个困扰——你的嵌套字段里有IPInstanceIdrating三个属性,现在按rating聚合时,桶列表里会同时混着这两个标识字段,但你希望每个文档只贡献其中一个(要么IP,要么InstanceId)到聚合结果里,对吧?

下面给你两种可行的实现方式,你可以根据自己的Elasticsearch版本和实际需求来选:

方式一:用脚本生成统一标识(最直接)

核心思路是在嵌套聚合内部,通过脚本动态生成一个统一标识字段:优先取IP的值,如果当前嵌套文档没有IP,就用InstanceId。这样每个嵌套文档只会对应一个标识,不会同时出现两个。

直接上示例DSL:

{
  "aggs": {
    "traverse_nested": {
      "nested": {
        "path": "你的嵌套字段名" // 替换成你实际的nested字段路径
      },
      "aggs": {
        "unique_identifier_buckets": {
          "terms": {
            "script": {
              "source": "doc['你的嵌套字段名.IP'].size() > 0 ? doc['你的嵌套字段名.IP'].value : doc['你的嵌套字段名.InstanceId'].value"
            }
          },
          "aggs": {
            "rating_aggregation": {
              // 这里换成你需要的rating聚合类型,比如stats/avg/max等
              "stats": {
                "field": "你的嵌套字段名.rating"
              }
            }
          }
        }
      }
    }
  }
}

小提示

  • 如果你的ES版本低于7.10,把脚本里的doc['field'].size() > 0换成doc.containsKey('field')就能正常判断字段是否存在了。
  • 要是你想优先保留InstanceId而非IP,只需要调换脚本里的判断顺序就行。

方式二:用过滤器拆分分组(更清晰区分两类标识)

如果你想明确分开统计IP和InstanceId各自的rating情况,不想把它们混在同一个terms桶里,可以先用filters聚合把数据分成“有IP的组”和“有InstanceId的组”,再分别做聚合:

示例DSL如下:

{
  "aggs": {
    "traverse_nested": {
      "nested": {
        "path": "你的嵌套字段名"
      },
      "aggs": {
        "split_by_identifier_type": {
          "filters": {
            "filters": {
              "ip_documents": {
                "exists": {
                  "field": "你的嵌套字段名.IP"
                }
              },
              "instance_id_documents": {
                "exists": {
                  "field": "你的嵌套字段名.InstanceId"
                }
              }
            }
          },
          "aggs": {
            "identifier_buckets": {
              "terms": {
                "script": {
                  "source": "doc['你的嵌套字段名.IP'].size() > 0 ? doc['你的嵌套字段名.IP'].value : doc['你的嵌套字段名.InstanceId'].value"
                }
              },
              "aggs": {
                "rating_stats": {
                  "stats": {
                    "field": "你的嵌套字段名.rating"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

这种方式的好处是,你能清晰看到两类标识各自的rating统计结果,而且每个标识只会出现在对应的分组桶里,不会交叉。

额外注意

确保你的IPInstanceId字段在映射里是可搜索的(别设成index: false),不然脚本没法读取它们的值哦。

内容的提问来源于stack exchange,提问作者John Diaz

火山引擎 最新活动