Elasticsearch 基础使用教程:从 MySQL 视角理解 ES
如果你熟悉 MySQL,学习 Elasticsearch 会容易很多——因为两者的很多概念是可以类比的。本文就用 MySQL 的思维方式来理解 Elasticsearch,帮你快速上手。
一、核心概念对照表
先看一张核心概念对照表,建立整体认知:
| MySQL | Elasticsearch | 说明 |
|---|---|---|
| Database(数据库) | Index(索引) | 数据的逻辑容器 |
| Table(表) | Index(索引) | ES 中 Index 既相当于数据库,也相当于表 |
| Row(行) | Document(文档) | 一条具体的数据记录 |
| Column(列) | Field(字段) | 数据的一个属性 |
| Schema(表结构) | Mapping(映射) | 定义字段类型和存储方式 |
| INSERT | POST / PUT | 插入数据 |
| SELECT | GET / POST _search | 查询数据 |
| UPDATE | POST _update | 更新数据 |
| DELETE | DELETE | 删除数据 |
| Index(索引) | 分片 + 副本 | MySQL 的索引是加速查询;ES 的分片是数据分片存储 |
💡 关键区别:MySQL 是关系型数据库,强调事务和关联;Elasticsearch 是搜索引擎,强调全文检索和实时分析。
二、创建”表”(创建索引)
MySQL 方式
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
email VARCHAR(100),
age INT,
created_at DATETIME,
INDEX idx_name (name),
INDEX idx_email (email)
);
Elasticsearch 方式
在 ES 中,创建索引可以显式定义 Mapping,也可以让 ES 自动推断:
# 创建索引并定义 Mapping(推荐)
PUT /users
{
"mappings": {
"properties": {
"name": { "type": "text" },
"email": { "type": "keyword" },
"age": { "type": "integer" },
"created_at": { "type": "date" }
}
}
}
类型说明:
text:全文搜索类型,会被分词(类似 MySQL 的 FULLTEXT 索引)keyword:精确匹配类型,不分词(类似 MySQL 的普通索引)integer、long、float:数值类型date:日期类型boolean:布尔类型
三、插入数据(INSERT → POST)
MySQL 方式
INSERT INTO users (name, email, age, created_at)
VALUES ('张三', '[email protected]', 28, '2024-01-15 10:30:00');
INSERT INTO users (name, email, age, created_at)
VALUES ('李四', '[email protected]', 32, '2024-01-16 14:20:00');
INSERT INTO users (name, email, age, created_at)
VALUES ('王五', '[email protected]', 25, '2024-01-17 09:00:00');
Elasticsearch 方式
# 插入单条文档(ES 自动生成 ID)
POST /users/_doc
{
"name": "张三",
"email": "[email protected]",
"age": 28,
"created_at": "2024-01-15T10:30:00"
}
# 插入单条文档(指定 ID)
PUT /users/_doc/1
{
"name": "张三",
"email": "[email protected]",
"age": 28,
"created_at": "2024-01-15T10:30:00"
}
# 批量插入
POST /_bulk
{"index": {"_index": "users"}}
{"name": "张三", "email": "[email protected]", "age": 28, "created_at": "2024-01-15T10:30:00"}
{"index": {"_index": "users"}}
{"name": "李四", "email": "[email protected]", "age": 32, "created_at": "2024-01-16T14:20:00"}
{"index": {"_index": "users"}}
{"name": "王五", "email": "[email protected]", "age": 25, "created_at": "2024-01-17T09:00:00"}
四、查询数据(SELECT → _search)
4.1 查询所有数据
MySQL:
SELECT * FROM users;
Elasticsearch:
GET /users/_search
{
"query": {
"match_all": {}
}
}
4.2 条件查询
MySQL:
SELECT * FROM users WHERE name = '张三';
Elasticsearch:
# 精确匹配(keyword 类型)
GET /users/_search
{
"query": {
"term": {
"email": "[email protected]"
}
}
}
# 全文搜索(text 类型,会被分词)
GET /users/_search
{
"query": {
"match": {
"name": "张三"
}
}
}
4.3 范围查询
MySQL:
SELECT * FROM users WHERE age >= 25 AND age < 30;
Elasticsearch:
GET /users/_search
{
"query": {
"range": {
"age": {
"gte": 25,
"lt": 30
}
}
}
}
4.4 多条件组合
MySQL:
SELECT * FROM users
WHERE age >= 25
AND (name LIKE '%张%' OR email LIKE '%example%')
ORDER BY created_at DESC
LIMIT 10;
Elasticsearch:
GET /users/_search
{
"query": {
"bool": {
"must": [
{ "range": { "age": { "gte": 25 } } }
],
"should": [
{ "match": { "name": "张" } },
{ "wildcard": { "email": "*example*" } }
],
"minimum_should_match": 1
}
},
"sort": [
{ "created_at": { "order": "desc" } }
],
"size": 10
}
bool 查询说明:
must:必须满足(类似 AND)should:满足任意一个即可(类似 OR)must_not:必须不满足(类似 NOT)filter:过滤条件,不参与评分(性能更好)
五、更新数据(UPDATE → _update)
MySQL 方式
UPDATE users SET age = 29 WHERE id = 1;
Elasticsearch 方式
# 部分更新
POST /users/_update/1
{
"doc": {
"age": 29
}
}
# 脚本更新(更灵活)
POST /users/_update/1
{
"script": {
"source": "ctx._source.age += params.increment",
"params": {
"increment": 1
}
}
}
⚠️ 注意:ES 的更新操作实际上是”标记删除 + 重新写入”,频繁更新会影响性能。
六、删除数据(DELETE → DELETE)
MySQL 方式
DELETE FROM users WHERE id = 1;
DELETE FROM users WHERE age < 20;
-- 删除整个表数据(保留表结构)
TRUNCATE TABLE users;
Elasticsearch 方式
# 删除单条文档
DELETE /users/_doc/1
# 按条件删除
POST /users/_delete_by_query
{
"query": {
"range": {
"age": { "lt": 20 }
}
}
}
# 删除整个索引(类似 DROP TABLE)
DELETE /users
七、聚合分析(GROUP BY → Aggregations)
MySQL 方式
-- 统计各年龄段的人数
SELECT
CASE
WHEN age < 20 THEN 'under_20'
WHEN age >= 20 AND age < 30 THEN '20_29'
WHEN age >= 30 AND age < 40 THEN '30_39'
ELSE '40_plus'
END AS age_group,
COUNT(*) as count,
AVG(age) as avg_age
FROM users
GROUP BY age_group;
Elasticsearch 方式
GET /users/_search
{
"size": 0,
"aggs": {
"age_groups": {
"range": {
"field": "age",
"ranges": [
{ "to": 20, "key": "under_20" },
{ "from": 20, "to": 30, "key": "20_29" },
{ "from": 30, "to": 40, "key": "30_39" },
{ "from": 40, "key": "40_plus" }
]
},
"aggs": {
"avg_age": {
"avg": { "field": "age" }
}
}
}
}
}
常用聚合类型:
| MySQL | Elasticsearch |
|---|---|
| COUNT(*) | value_count |
| SUM(field) | sum |
| AVG(field) | avg |
| MAX(field) / MIN(field) | max / min |
| GROUP BY | terms(分组)、range(范围分组) |
八、分页查询
MySQL 方式
-- 第 1 页,每页 10 条
SELECT * FROM users LIMIT 0, 10;
-- 第 2 页
SELECT * FROM users LIMIT 10, 10;
-- 第 3 页
SELECT * FROM users LIMIT 20, 10;
Elasticsearch 方式
# 使用 from + size(类似 MySQL LIMIT)
GET /users/_search
{
"from": 0,
"size": 10,
"query": { "match_all": {} }
}
# 第 2 页
GET /users/_search
{
"from": 10,
"size": 10,
"query": { "match_all": {} }
}
# 深分页(数据量大时推荐使用 search_after)
GET /users/_search
{
"size": 10,
"query": { "match_all": {} },
"sort": [
{ "created_at": "desc" },
{ "_id": "asc" }
],
"search_after": [1704067200000, "abc123"]
}
⚠️ 注意:ES 的 from + size 默认限制最大 10000 条,深分页建议使用 search_after 或 scroll API。
九、MySQL vs ES:什么时候用哪个?
| 场景 | 推荐 | 原因 |
|---|---|---|
| 事务处理(订单、支付) | MySQL | ES 不支持事务 |
| 复杂关联查询 | MySQL | ES 关联能力有限 |
| 全文搜索 | Elasticsearch | ES 天生为搜索而生 |
| 日志分析 | Elasticsearch | ES 写入和聚合性能强 |
| 实时监控大屏 | Elasticsearch | ES 聚合查询速度快 |
| 主数据存储 | MySQL | ES 数据可能丢失(近实时) |
常见架构:MySQL 作为主存储,数据同步到 ES 做搜索和分析。
┌──────────┐ 同步 ┌──────────────┐
│ MySQL │ ──────────► │ Elasticsearch │
│ (主存储) │ │ (搜索/分析) │
└──────────┘ └──────────────┘
│ │
│ │
▼ ▼
业务写入 搜索/分析查询
十、快速参考:常用 API
# 查看所有索引
GET /_cat/indices?v
# 查看索引 mapping
GET /users/_mapping
# 查看索引设置
GET /users/_settings
# 查看集群健康状态
GET /_cluster/health
# 查看节点信息
GET /_cat/nodes?v
# 查看索引统计
GET /users/_stats
总结
从 MySQL 视角理解 Elasticsearch:
- Index ≈ Database + Table:一个索引就是一个数据容器
- Document ≈ Row:JSON 格式的一行数据
- Mapping ≈ Schema:定义字段类型
- Query DSL ≈ SQL:用 JSON 格式表达查询条件
- Aggregation ≈ GROUP BY:强大的聚合分析能力
掌握这些对应关系,你就能快速上手 Elasticsearch 了!
下一篇预告:Elasticsearch 进阶使用 —— 复合查询、脚本、分析器详解