Elasticsearch索引 = Mapping?
·
不,Elasticsearch 索引(Index) ≠ Mapping。
这是两个紧密关联但本质不同的概念:
- 索引(Index) 是 数据的容器(类似数据库中的“表”)
- Mapping(映射) 是 索引的结构定义(类似“表结构”或“Schema”)
将二者等同,会导致对 ES 数据模型的根本性误解。
一、本质区别:容器 vs 结构
| 维度 | 索引(Index) | Mapping(映射) |
|---|---|---|
| 角色 | 数据存储单元 | 字段结构定义 |
| 类比 | MySQL 的 数据库表(table) | MySQL 的 表结构(CREATE TABLE …) |
| 内容 | 包含文档(Documents)、分片(Shards)、设置(Settings) | 定义字段类型(text/keyword/integer)、分析器、是否可聚合等 |
| 变更 | 可动态增删文档 | 字段类型一旦设定,不可修改(需重建索引) |
💡 核心认知:
Mapping 是 Index 的“基因蓝图”,Index 是 Mapping 的“物理载体”
二、包含关系:Index 包含 Mapping
一个完整的 Index 定义包含两部分:
PUT /products
{
"settings": { ... }, // ← 索引设置(分片数、刷新间隔等)
"mappings": { ... } // ← 映射(字段结构定义)
}
▶ 1. Settings(设置)
- 控制 索引的物理行为:
{ "number_of_shards": 3, "number_of_replicas": 1, "refresh_interval": "30s" }
▶ 2. Mappings(映射)
- 控制 数据的逻辑结构:
{ "properties": { "name": { "type": "text" }, "price": { "type": "float" }, "brand": { "type": "keyword" } } }
✅ 关键结论:
Mapping 是 Index 的子集,Index 是 Mapping 的宿主
三、实战中的典型误区
▶ 误区 1:“创建了 Index 就有 Mapping”
- 事实:
- 若未显式定义 Mapping,ES 会根据 第一条文档 动态生成
- 动态 Mapping 常导致 字段类型错误(如字符串数字被设为
text)
- 后果:
- 无法范围查询(
range) - 聚合结果异常
- 无法范围查询(
- 正确做法:
始终显式定义 Mapping:PUT /products { "mappings": { "properties": { "user_id": { "type": "long" }, // 避免被设为 text "name": { "type": "text" } } } }
▶ 误区 2:“修改 Mapping 就是修改 Index”
- 事实:
- 字段类型不可变(如
text→keyword需重建索引) - 只能 新增字段,不能修改现有字段类型
- 字段类型不可变(如
- 正确流程:
- 创建新索引(带正确 Mapping)
- 用
_reindex迁移数据 - 切换别名(Alias)
▶ 误区 3:“Index 名称影响 Mapping”
- 事实:
- Index 名称仅用于路由和管理
- 同一 Mapping 可用于多个 Index(如日志按天分索引:
logs-2024-07-24)
四、PHP 实战:Laravel 中的 Index 与 Mapping
▶ 步骤 1:创建 Index + Mapping
$client = \Elasticsearch\ClientBuilder::create()->build();
$params = [
'index' => 'products',
'body' => [
'settings' => [
'number_of_shards' => 1,
'refresh_interval' => '30s'
],
'mappings' => [
'properties' => [
'name' => [
'type' => 'text',
'fields' => ['keyword' => ['type' => 'keyword']]
],
'price' => ['type' => 'float'],
'user_id' => ['type' => 'long'] // 关键!避免 text
]
]
]
];
$client->indices()->create($params);
▶ 步骤 2:验证 Mapping
// 获取当前 Mapping
$mapping = $client->indices()->getMapping(['index' => 'products']);
print_r($mapping['products']['mappings']);
五、终极心法
**“Index 不是结构,
而是数据的家园——
- 当你 定义 Mapping,
你在设计家园蓝图;- 当你 创建 Index,
你在建造物理空间;- 当你 协同二者,
你在构建高效搜索系统。真正的 ES 大师,
始于对概念的敬畏,
成于对细节的精控。”
结语
从今天起:
- 所有 Index 必显式定义 Mapping
- ID/数字字段必用
long/integer - 修改字段类型必走 Reindex 流程
因为最好的搜索系统,
不是临时拼凑,
而是结构先行。
所有评论(0)