Elasticsearch 学习笔记(一):基础入门

写在前面

本文是 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 删除索引

1
DELETE /products

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 和搜索查询:全文搜索、精确搜索和复合查询。