ElasticSearch使用copy_to字段做多字段高效分组聚合问题咨询
问题根因
copy_to的作用是将多个源字段的值作为独立元素存入目标字段的数组,你写入测试数据后,aggCondition实际存储的是["192.0.0.1", "192.0.1.1"]这类数组。对aggCondition.keyword做terms聚合时,会按数组内每个单独的IP分组统计,所以每个IP计数为2,无法实现多字段组合分组的效果。
方案1:使用multi_terms聚合(ES 7.12及以上版本推荐)
multi_terms是ES 7.12推出的原生多字段联合分组聚合,性能远高于脚本聚合,无需修改现有mapping和写入逻辑,直接支持多字段分组需求,适配你9个字段的场景。
测试场景查询语句如下:
GET /test_index/_search { "size": 0, "aggs": { "Ips": { "multi_terms": { "terms": [ {"field": "srcIp.keyword"}, {"field": "dstIp.keyword"} ] } } } }
返回结果的bucket key为数组格式,如["192.0.0.1", "192.0.1.1"],和你预期的格式一致,需要的话可自行做字符串格式化。如果是9个字段分组,只需在terms数组中依次添加对应字段即可。
方案2:写入前预处理组合字段(全版本兼容,性能最优)
如果你使用的ES版本低于7.12,推荐在数据写入ES前,将需要分组的9个字段用不会出现在字段值中的分隔符(如||、#等)拼接为一个单独的字符串,存入专门的聚合字段,mapping设置为keyword类型。后续直接对该字段做terms聚合即可得到预期结果。
临时查询替代方案
如果不想修改写入逻辑,也无法使用multi_terms,可使用runtime字段在查询时拼接字段,性能略低于前两种方案,仅适合临时查询:
GET /test_index/_search { "size": 0, "runtime_mappings": { "combined_ip": { "type": "keyword", "script": "emit(doc['srcIp.keyword'].value + ' ' + doc['dstIp.keyword'].value)" } }, "aggs": { "Ips": { "terms": { "field": "combined_ip", "size": 100 } } } }
内容的提问来源于stack exchange,提问作者sr ao
相关产品推荐
相关产品推荐

