写在前面
本文是 Elasticsearch 学习笔记系列的第一篇,介绍 ES 的核心概念、倒排索引原理和基本操作。基于 ES 8.15 版本。无论你是做搜索还是日志分析,这篇都是入门的基础。
一、Elasticsearch 是什么
1.1 定义
Elasticsearch 是一个基于 Lucene 的分布式搜索和分析引擎。
1
2
3
4
5
6
|
核心能力:
- 全文搜索 — 毫秒级从海量文本中找到匹配结果
- 结构化搜索 — 按字段精确过滤(数值、日期、枚举)
- 聚合分析 — 统计、分组、指标计算
- 分布式 — 水平扩展,处理 PB 级数据
- 近实时 — 数据写入后约 1 秒可搜索
|
1.2 典型应用场景
1
2
3
4
5
|
应用搜索 — 电商商品搜索、文档搜索
日志分析 — ELK 技术栈(ES + Logstash + Kibana)
监控告警 — 系统指标、业务指标聚合分析
安全分析 — SIEM,安全事件检索和关联
业务数据看板 — 实时统计报表
|
1.3 ELK 生态
1
2
3
4
|
Elasticsearch — 存储和搜索引擎
Kibana — 可视化和查询界面
Logstash — 数据采集和转换
Beats — 轻量级数据采集器(Filebeat、Metricbeat 等)
|
二、核心概念
2.1 与关系型数据库的类比
1
2
3
4
5
6
7
8
9
|
MySQL Elasticsearch
───────────────── ─────────────────
Database Index(索引)
Table Index(一个 Index 就是一张表)
Row Document(文档)
Column Field(字段)
Schema Mapping(映射)
SQL DSL(Query DSL / REST API)
PRIMARY KEY _id
|
2.2 核心术语
1
2
3
4
5
6
7
8
|
Index(索引) — 文档的集合,类似数据库
Document(文档) — 一条数据,JSON 格式
Field(字段) — 文档中的一个属性
Mapping(映射) — 定义索引的字段类型和属性
Shard(分片) — 索引的物理分片,分布式存储
Replica(副本) — 分片的复制,提供高可用
Node(节点) — 一个 ES 实例
Cluster(集群) — 多个节点组成
|
2.3 文档结构
1
2
3
4
5
6
7
8
9
10
11
12
|
{
"_index": "products",
"_id": "1",
"_source": {
"name": "华为 Mate 60 Pro",
"brand": "华为",
"price": 6999,
"category": "手机",
"in_stock": true,
"created_at": "2026-01-15"
}
}
|
1
2
3
|
_index — 文档所在的索引
_id — 文档唯一标识(自动生成或指定)
_source — 文档原始内容(业务数据)
|
三、倒排索引
3.1 正排索引 vs 倒排索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
正排索引(传统数据库):
Doc 1 → "华为 Mate 60 Pro"
Doc 2 → "华为 Mate Pad"
Doc 3 → "苹果 iPhone 15"
查询 "华为" → 扫描每一条记录 → 慢
倒排索引(ES):
"华为" → [Doc 1, Doc 2]
"mate" → [Doc 1, Doc 2]
"60" → [Doc 1]
"pro" → [Doc 1]
"苹果" → [Doc 3]
"iphone" → [Doc 3]
"15" → [Doc 3]
查询 "华为" → 直接查倒排索引 → [Doc 1, Doc 2] → 快
|
3.2 倒排索引的构建过程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
原文: "华为 Mate 60 Pro"
1. 分词(Tokenization)
→ ["华为", "mate", "60", "pro"]
2. 归一化(Normalization)
→ 小写、去停用词、词干提取等
→ ["华为", "mate", "60", "pro"]
3. 建立倒排表
Token → Doc IDs
"华为" → [1]
"mate" → [1]
"60" → [1]
"pro" → [1]
|
3.3 为什么 ES 快
1
2
3
4
|
1. 倒排索引 — 直接定位文档,不需要全表扫描
2. 分片并行 — 查询分发到多个分片并行执行
3. 缓存 — 查询结果缓存、文件系统缓存
4. 列式存储 — Doc Values 支持高效的聚合和排序
|
四、安装和连接
4.1 Docker 安装(开发环境)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# 创建网络
docker network create elastic
# 启动 ES(单节点)
docker run -d \
--name elasticsearch \
--net elastic \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
-e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
docker.elastic.co/elasticsearch/elasticsearch:8.15.0
# 启动 Kibana
docker run -d \
--name kibana \
--net elastic \
-p 5601:5601 \
-e "ELASTICSEARCH_HOSTS=http://elasticsearch:9200" \
docker.elastic.co/kibana/kibana:8.15.0
|
1
2
3
|
ES API: http://localhost:9200
Kibana UI: http://localhost:5601
Dev Tools: http://localhost:5601/app/dev_tools
|
4.2 验证连接
1
2
3
4
5
|
# curl 方式
curl http://localhost:9200
# Kibana Dev Tools
GET /
|
返回:
1
2
3
4
5
6
|
{
"name": "elasticsearch",
"version": {
"number": "8.15.0"
}
}
|
五、索引管理
5.1 创建索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// 显式创建索引 + Mapping
PUT /products
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "ik_max_word" },
"brand": { "type": "keyword" },
"price": { "type": "float" },
"category": { "type": "keyword" },
"in_stock": { "type": "boolean" },
"created_at": { "type": "date", "format": "yyyy-MM-dd" },
"description": { "type": "text", "analyzer": "ik_max_word" },
"tags": { "type": "keyword" }
}
}
}
|
5.2 查看索引
1
2
3
4
5
6
7
8
9
10
11
|
// 查看索引信息
GET /products
// 查看索引 Mapping
GET /products/_mapping
// 查看索引 Settings
GET /products/_settings
// 查看所有索引
GET /_cat/indices?v
|
5.3 删除索引
5.4 修改索引设置
1
2
3
4
5
6
7
8
9
|
// 修改副本数(可以动态修改)
PUT /products/_settings
{
"index": {
"number_of_replicas": 2
}
}
// 注意:分片数(number_of_shards)创建后不能修改
|
六、Mapping 详解
6.1 字段类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
文本类型:
text — 全文搜索,会分词(用于搜索)
keyword — 精确匹配,不分词(用于过滤、排序、聚合)
数值类型:
integer, long, float, double, scaled_float
日期类型:
date — 支持多种格式
布尔类型:
boolean
复杂类型:
object — 嵌套对象
nested — 嵌套数组(独立查询)
array — 数组(ES 没有专门的 array 类型,任何字段都可以是数组)
特殊类型:
geo_point — 经纬度
ip — IP 地址
completion — 自动补全建议
flattened — 整个对象作为 keyword
|
6.2 text vs keyword
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
// text:分词后建立倒排索引
"name": { "type": "text" }
// "华为 Mate 60" → ["华为", "mate", "60"]
// 搜索 "华为" 可以匹配
// keyword:不分词,整体建立索引
"brand": { "type": "keyword" }
// "华为 Mate 60" → ["华为 Mate 60"]
// 必须完全匹配 "华为 Mate 60" 才能搜到
// 常见用法:同时支持全文搜索和精确匹配
"title": {
"type": "text",
"fields": {
"keyword": { "type": "keyword" }
}
}
// title 字段:text 模式用于全文搜索
// title.keyword 子字段:keyword 模式用于精确匹配、排序、聚合
|
6.3 动态映射
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
ES 默认启用动态映射:写入文档时,如果字段不存在,自动推断类型
自动推断规则:
字符串 → text + keyword 子字段
整数 → long
浮点数 → float
布尔值 → boolean
日期 → date(如果格式匹配)
对象 → object
问题:
- 类型推断可能不准确
- 一旦确定无法修改(只能 reindex)
建议:
生产环境提前定义 Mapping,关闭动态映射或设为 strict
|
1
2
3
4
5
6
7
8
9
10
|
PUT /products
{
"mappings": {
"dynamic": "strict",
"properties": {
"name": { "type": "text" }
}
}
}
// 写入未定义的字段会报错
|
6.4 常用 Mapping 设置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "ik_max_word",
"index": true
},
"description": {
"type": "text",
"analyzer": "ik_max_word",
"index": true
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
},
"is_active": {
"type": "boolean"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"metadata": {
"type": "flattened"
}
}
}
}
|
1
2
3
4
|
index: true/false — 是否索引(false 则不能搜索但可以存储)
analyzer — 分词器
format — 日期格式(|| 分隔多种格式)
scaling_factor — 浮点数缩放因子(scaled_float 存为 long,避免精度问题)
|
七、索引模板
7.1 创建模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 匹配 logs-* 的索引自动应用此模板
PUT /_index_template/logs_template
{
"index_patterns": ["logs-*"],
"priority": 100,
"template": {
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"index.lifecycle.name": "logs-policy"
},
"mappings": {
"properties": {
"timestamp": { "type": "date" },
"level": { "type": "keyword" },
"service": { "type": "keyword" },
"message": { "type": "text", "analyzer": "ik_max_word" },
"trace_id": { "type": "keyword" },
"host": { "type": "keyword" }
}
}
}
}
|
7.2 组件模板
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
// 可复用的设置组件
PUT /_component_template/common_settings
{
"template": {
"settings": {
"number_of_replicas": 1,
"refresh_interval": "5s"
}
}
}
// 在索引模板中引用
PUT /_index_template/app_template
{
"index_patterns": ["app-*"],
"composed_of": ["common_settings"],
"template": {
"mappings": {
"properties": {
"name": { "type": "text" }
}
}
}
}
|
八、索引别名
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
// 创建别名
POST /_aliases
{
"actions": [
{
"add": {
"index": "products-v1",
"alias": "products"
}
}
]
}
// 通过别名操作(应用层不需要知道实际索引名)
GET /products/_search
{ "query": { "match_all": {} } }
// 无缝切换索引(零停机)
POST /_aliases
{
"actions": [
{ "remove": { "index": "products-v1", "alias": "products" } },
{ "add": { "index": "products-v2", "alias": "products" } }
]
}
|
九、_cat API 速查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# 集群健康
GET /_cat/health?v
# 节点信息
GET /_cat/nodes?v
# 索引列表
GET /_cat/indices?v
# 分片状态
GET /_cat/shards?v
# 别名
GET /_cat/aliases?v
# 已分配的分片
GET /_cat/allocation?v
# 恢复进度
GET /_cat/recovery?v
# 所有 ?v 参数表示显示列名
# ?format=json 输出 JSON 格式
# ?h=field1,field2 只显示指定列
|
十、小结
本文学习了 Elasticsearch 的基础:
- ES 是什么和应用场景
- 核心概念(Index、Document、Mapping、Shard、Replica)
- 倒排索引原理
- 安装和连接
- 索引管理(创建、查看、删除、Settings)
- Mapping 详解(字段类型、text vs keyword、动态映射)
- 索引模板和别名
- _cat API 速查
下一篇将学习文档 CRUD 和搜索查询:全文搜索、精确搜索和复合查询。