Elasticsearch中field与field.keyword的区别及Kibana字段重复问题咨询
这个问题其实是Elasticsearch默认的动态字段映射行为导致的,我来给你拆解清楚各个点:
为什么会出现两个字段(原字段 + field.keyword)?
当你没有提前手动定义字段的映射规则时,Elasticsearch会自动检测字段类型并生成对应的映射。对于字符串类型的字段,ES默认会创建两种索引方式:
- 一个是常规的
text类型字段(就是你看到的原字段名),用于全文搜索; - 另一个是
keyword类型的子字段(格式为field.keyword),用于精确匹配、排序和聚合。
Kibana会读取ES的映射信息,所以这两个字段都会被展示出来。
原字段与field.keyword的核心区别
原text字段:
它会对字符串内容做分词处理——比如把"Elasticsearch is cool"拆分成["elasticsearch", "is", "cool"]三个词项。这样你搜索其中任意一个词,都能匹配到包含该内容的文档,非常适合全文检索场景。但因为字段值被拆成了多个独立词项,没法直接用来做分组统计。field.keyword字段:
它不会对字符串做分词,而是把整个字符串当作单一完整的词项存储。比如"Elasticsearch is cool"会被完整保存为一个词项。这种特性让它适合做精确匹配(比如筛选出值恰好是"Elasticsearch is cool"的文档)、排序,以及聚合操作。默认情况下,它还会启用doc_values(一种专为聚合和排序优化的存储结构),而text字段默认不开启这个配置。
关于“可聚合”的具体含义
聚合操作(比如统计每个值的出现次数、计算平均值这类)的核心需求是:字段的值必须是可被精确分组的单一项。
对于text字段来说,因为内容被分词成多个词项,聚合时会把每个分词后的词单独统计——比如你有个字段是"北京市朝阳区",text字段分词后可能拆成["北京", "市", "朝阳", "区"],聚合结果会是这四个词的各自统计数,这显然不是我们想要的结果。
而keyword字段是完整存储的,每个文档的该字段值都是一个精确的、不可拆分的项,所以可以直接按照这个值来分组统计(比如统计每个城市的文档数量),这就是“可聚合”的具体含义。另外,排序操作也依赖这种精确的单一值,所以keyword字段支持排序,而text字段默认不支持。
额外补充:自定义映射控制字段生成
如果你不需要自动生成的keyword子字段,或者想自定义它的规则,可以手动创建索引映射。比如:
PUT /my_custom_index { "mappings": { "properties": { "my_field": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 // 超过256字符的内容不存入keyword字段 } } } } } }
这其实就是ES默认动态映射生成的结构,你可以根据需求调整ignore_above或者干脆移除fields配置来取消keyword子字段。
内容的提问来源于stack exchange,提问作者tomak

