分布式全文检索引擎ElasticSearch-常用mapping讲解

时间:2024-12-14 15:44:15

一、什么是mapping?

mapping就是映射,可以简单理解为数据类型,只不过是规定了索引中每个字段的数据类型,我们以传统关系型数据库为例,数据库建表的时候,我们DDL依据一般都会指定每个字段的存储类型,例如:varchar、int、datetime等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱,在Elasticsearch中也是这样,创建索引的时候一般也需要指定索引的字段类型,这种方式称为映射(Mapping)

那么指定映射有两种方式,被动创建(也叫动态映射)主动创建(也叫显式映射)

1、动态映射

此时字段和映射类型不需要事先定义,只需要存在文档的索引,当向此索引添加数据的时候当遇到不存在的映射字段,ES会根据数据内容自动添加映射字段定义。

相当于对于一个字段,自动的识别并定义其类型

那他自动识别的规则是什么呢?请看下表

左列是给定的数据所属类型,右列识别成对应的ES数据类型

数据类型 ElasticSearch 数据类型
null 不添加任何字段
true或者false boolean类型
浮点数据 float类型
integer数据 long类型
object object类型
array 取决于数组中的第一个非空值的类型。
string 如果此内容通过了日期格式检测,则会被认为是date数据类型
如果此值通过了数值类型检测则被认为是double或者long数据类型
带有关键字子字段会被认为一个text字段

但需要注意的是, 一般生产环境下需要禁用动态映射,使用动态映射可能出现以下问题

  • 造成集群元数据一直变更,导致不稳定;
  • 可能造成数据类型与实际类型不一致;
  • 对于一些异常字段或者是扫描类的字段,也会频繁的修改mapping,导致业务不可控。

2、显式映射

这就是我们手动来指定某个字段是什么类型

PUT mapping_demo
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ik_smart": {
          "type": "ik_smart"
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "name": {
          "type": "keyword"  // 禁用分词,适用于聚合和排序
        },
        "city": {
          "type": "text",
          "analyzer": "ik_smart",  // 使用 ik_smart 分析器进行中文分词
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "age": {
          "type": "integer"  // 指定 age 字段为整数类型
        },
        "joined": {
          "type": "date",  // 指定 joined 字段为日期类型
          "format": "yyyy-MM-dd||epoch_millis"
        }
      }
    }
  }
}

可以看到,我们是在每个字段中,用type来指定对应的映射类型

二、常用映射类型

1、字符串形式的类型

1)text类型

当一个字段是要被全文搜索的,比如Email内容、产品描述,应该使用text类型,text类型会被分词

设置text类型以后,字段内容会被分词,在生成倒排索引以前,字符串会被分析器分成一个一个词项,text类型的字段不用于排序,很少用于聚合

2)keyword类型

keyword类型不会被分词,常用于关键字搜索,比如姓名、email地址、主机名、状态码和标签等

如果字段需要进行过滤(比如查姓名是张三发布的博客)、排序、聚合,keyword类型的字段只能通过精确值搜索到(等值查询),常常被用来过滤、排序和聚合

2、数值形式的类型

数字类型也是我们最常用的类型之一,下面我们看下数字类型的使用

类型 取值范围
long -263 ~ 263
integer -231 ~ 231
short -215 ~ 215
byte -27 ~ 27
double 64位的双精度 IEEE754 浮点类型
float 32位的双精度 IEEE754 浮点类型
half_float 16位的双精度 IEEE754 浮点类型
scaled_float 缩放类型的浮点类型(理解成保留几位小数)
  • 在满足需求的情况下,优先使用范围小的字段,字段长度越小,索引和搜索的效率越高。

3、日期类型

ES如何处理日期

在ES的内部,时间会被转换为UTC时间(如果声明了时区)并使用从新纪元开始的毫秒数的长整形数字类型的进行存储,在日期字段上的查询,内部将会转换为使用长整形的毫秒进行范围查询,根据与字段关联的日期格式,聚合和存储字段的结果将转换回字符串

注意点:日期最终都会作为字符串呈现,即使最开始初始化的时候是利用long声明的

 日期的格式可以被定制化的,如果没有声明日期的格式,它将会使用默认的格式:

"strict_date_optional_time||epoch_millis"

这意味着它将会接收带时间戳的日期,它将遵守strict_date_optional_time限定的格式(yyyy-MM-dd'T'HH:mm:ss.SSSZ 或者 yyyy-MM-dd)或者毫秒数

举个例子:

PUT mapping_demo/_mapping
{
  "properties": {
    "datetime": {
        "type": "date",
        "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
     }
  }
}
# 添加数据
PUT mapping_demo/_doc/2
{
  "name":"河北区",
  "city":"河北省小区",
  "datetime":"2022-02-21 11:35:42"
}

4、布尔类型

boolean类型用于存储文档中的true/false

5、范围类型

顾名思义,范围类型字段中存储的内容就是一段范围,例如年龄30-55岁,日期在2020-12-28到2021-01-01之间等

ES中有6种范围类型

  • integer_range
  • float_range
  • long_range
  • double_range
  • date_range
  • ip_range
PUT mapping_demo/_mapping
{
  "properties": {
    "age_range": {
        "type": "integer_range"
     }
  }
}

# 指定年龄范围,可以使用 gt、gte、lt、lte。
PUT mapping_demo/_doc/3
{
  "name":"张三",
  "age_range":{
    "gt":20,
    "lt":30
  }
}