
作者介绍:简历上没有一个精通的运维工程师,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。

中间件,我给它的定义就是为了实现某系业务功能依赖的软件,包括如下部分:
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
      }
    }
  }
}'可以和前面未指定对比下参数有什么区别。