作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。
中间件,我给它的定义就是为了实现某系业务功能依赖的软件,包括如下部分:
Web服务器
代理服务器
ZooKeeper
Kafka
RabbitMQ
Hadoop HDFS
Elasticsearch ES (本章节)
其实在我们前面的章节里面已经涉及到这个映射(Mapping)概念,今天我们来详细介绍下他。想象一下关系型数据库(如 MySQL,虽然我还未讲解他,下个章节就会涉及到数据库)。在创建表之前,你需要定义表结构:表名、列名、每列的数据类型(VARCHAR, INT, DATE等)、是否允许 NULL、默认值、索引等。Elasticsearch 的 Mapping 扮演着完全相同的角色!
我们前面在ES的读写操作里面已经向里面插入过一些数据,但是我们并没有单独定义这个Mapping,当 Elasticsearch 索引未手动创建 Mapping 时,首次写入数据会触发 自动生成 Mapping(Dynamic Mapping)
1.写入数据,不指定Mapping
这个等效于MySQL里面的创建表结构,并插入一条数据。
# 向不存在的索引写入数据(自动创建索引)
curl -X POST "http://192.168.31.173:9200/auto_index/_doc" -H 'Content-Type: application/json' -d'
{
"name": "Alice",
"age": 30,
"active": true,
"join_date": "2023-05-15"
}
2.查看对应的Mapping
[root@localhost ~]# curl -X GET "http://192.168.31.172:9200/auto_index/_mapping?pretty"
{
"auto_index" : {
"mappings" : {
"properties" : {
"active" : {
"type" : "boolean" #布尔型
},
"age" : {
"type" : "long" #长整型
},
"join_date" : {
"type" : "date" #日期格式
},
"name" : {
"type" : "text", #文本类型
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
3.写入数据前先创建Mapping
这个操作实际上就等效于MySQL里面的创建表结构。
[root@localhost ~]# curl -X PUT "http://192.168.31.173:9200/simple_index" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"name": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"age": {
"type": "integer"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd"
},
"is_active": {
"type": "boolean"
},
"ip_address": {
"type": "keyword"
}
}
}
}
'
{"acknowledged":true,"shards_acknowledged":true,"index":"simple_index"}[root@localhost ~]#
其实无论我们提前创建Mapping还是插入数据自动生成,都会涉及到一个问题,那就是我后面插入的数据如果和前面的标准Mapping下不一致会出现什么情况。这个情况如果是在M有SQL里面则会插入失败,因为MySQL会严格查询数据结构,如果对不上则会插入失败,而这个问题在ES里面则会分为下面几种情况。
1.减少字段
// Mapping 定义
"properties": {
"name": {"type": "text"},
"age": {"type": "integer"}
}
// 插入数据(缺失 age 字段)
{
"name": "张三"
}
结果:文档成功写入,age
字段值为 null。
2.增加字段
// 已有 Mapping
"properties": {"name": {"type": "text"}}
// 插入数据(新增 email 字段)
{
"name": "李四",
"email": "lisi@example.com" // 新字段
}
结果:文档成功写入,Mapping 自动扩展。
3.变更字段
// 已有 Mapping
"properties": {"age": {"type": "integer"}}
// 尝试插入冲突数据
{
"age": "twenty five" // 字符串 vs integer
}
{
"error": {
"type": "mapper_parsing_exception",
"reason": "failed to parse field [age] of type [integer]"
}
}
上面提到的3种情况,是基于ES默认的配置情况下,实际生产环境我们提前创建Mapping,并严格控制ES的行为,比如不允许增加字段。在ES里面Mapping一旦创建成功,不允许修改(自动扩展不算)。所以我们需要在创建Mapping的时候指定不允许增加字段。
curl -X PUT "http://192.168.31.172:9200/new_auto_index" -H 'Content-Type: application/json' -d'
{
"mappings": {
"dynamic": "strict", # 修改为严格模式
"properties": {
"active": {
"type": "boolean"
},
"age": {
"type": "integer" # 从 long 改为 integer
},
"join_date": {
"type": "date",
"format": "yyyy-MM-dd" # 指定日期格式
},
"name": {
"type": "keyword" # 从 text 改为 keyword
}
}
}
}'
可以和前面未指定对比下参数有什么区别。