Elasticsearch 全栈教程:从入门到精通
目录
-
(图片来源网络,侵删)- 什么是 Elasticsearch?
- 它能做什么?(典型应用场景)
- 核心特点与优势
- 与传统数据库的对比
-
- 集群与节点
- 索引
- 文档
- 分片与副本
- 倒排索引
-
- 环境要求
- 安装 Elasticsearch
- 安装 Kibana (开发者必备工具)
- 验证安装
-
- 交互工具:Kibana Dev Tools
- CRUD 操作
- 创建文档
- 读取文档
- 更新文档
- 删除文档
- 搜索入门
GET请求搜索query string搜索query DSL搜索 (推荐)
-
(图片来源网络,侵删)- 搜索的基本结构
bool查询:组合查询的利器must(必须匹配)should(应该匹配,影响相关性)filter(必须匹配,但不计算分数)must_not(必须不匹配)
- 其他常用查询
match(全文匹配)term(精确值匹配)range(范围查询)wildcard(通配符查询)fuzzy(模糊查询)
- 排序与分页
- 聚合分析:从数据中提取洞察
- 桶聚合
- 度量聚合
-
- 数据建模:Mapping
- 动态映射 vs. 静态映射
- 常用数据类型
- 自定义 Mapping
- 分析器:分词与标准化
- 什么是分析器?
- 标准分析器 工作流程
- 内置分析器
- 自定义分析器
- 索引模板与生命周期管理
- 安全:基础认证与 TLS
- 数据建模:Mapping
-
- 集群健康状态
- 备份与恢复
- 监控
- 性能调优简介
-
- 官方文档
- 推荐书籍
- 社区与博客
第一部分:初识 Elasticsearch
什么是 Elasticsearch?
Elasticsearch 是一个基于 Lucene 库构建的 开源、分布式、RESTful 风格 的 搜索引擎,它被设计用于处理大规模数据的实时搜索、分析和存储。

你可以把它想象成一个 “超级数据库”,但它不擅长事务性操作(比如银行转账),而是极其擅长 “快速查找和分析”。
它能做什么?(典型应用场景)
- 网站搜索:为电商、新闻、博客等网站提供强大的全文检索功能。
- 日志分析:收集、存储和分析来自服务器、应用、网络设备的海量日志,是 ELK/EFK 技术栈的核心,常用于实时监控、故障排查和安全审计。
- 指标监控:存储和查询时间序列数据,用于系统性能监控和可视化。
- 安全分析:通过搜索和分析安全事件日志,检测异常行为和潜在威胁。
- 商业智能:对业务数据进行聚合分析,生成报表和仪表盘。
核心特点与优势
- 分布式:数据被分散存储在多个节点上,易于水平扩展,处理 PB 级数据。
- 高可用:支持数据副本,当某个节点宕机时,副本可以自动提升为主节点,保证服务不中断。
- 实时性:数据写入后几乎可以立即被搜索到,延迟通常在毫秒级。
- 全文检索:对文本内容进行智能分词,支持同义词、拼音、模糊等高级搜索。
- 强大的聚合能力:不仅能搜索,还能对数据进行分组、计算、统计,实现复杂的数据分析。
- RESTful API:通过简单的 HTTP 接口进行所有操作,易于集成到任何语言和框架中。
与传统数据库的对比
| 特性 | Elasticsearch | 传统数据库 (如 MySQL) |
|---|---|---|
| 核心目的 | 搜索、分析 | 事务处理、存储 |
| 数据模型 | 文档型 (JSON) | 关型 (表、行、列) |
| 扩展性 | 水平扩展 (增加更多节点) | 垂直扩展 (更强的单机) |
| 事务支持 | 不支持 ACID 事务 | 支持 ACID 事务 |
| 查询语言 | Query DSL (JSON) | SQL |
| 实时性 | 近实时 | 实时或最终一致 |
第二部分:核心概念
理解这些概念是掌握 Elasticsearch 的关键。
集群与节点
- 节点:一个 Elasticsearch 的运行实例,它存储数据,并参与集群的索引和搜索功能。
- 集群:由一个或多个具有相同
cluster.name的节点组成,它们协同工作,共享数据和负载,一个集群可以只有一个节点。
索引
- 索引是 具有相似特征的文档的集合,类似于关系数据库中的 “数据库” 或 “表”。
- 索引名必须是小写字母,不能以下划线开头。
文档
- 文档是 Elasticsearch 中 信息的基本单元,是一个 JSON 格式的对象。
- 它类似于关系数据库中的一 “行”。
- 每个文档都有一个唯一的
_id。
分片与副本
- 分片:一个索引可以被拆分成多个分片,每个分片本身就是一个功能完备的、独立的索引,可以被放置在集群的任何节点上,分片是 Elasticsearch 水平扩展 的核心,一个索引的分片数量在创建后就不能改变。
- 副本:分片的副本是分片的 拷贝,副本提供了 高可用性 和 扩展查询能力,如果持有主分片的节点宕机,副本分片可以被提升为新的主分片,副本的数量可以随时调整。
倒排索引
这是 Elasticsearch 实现快速搜索的 核心技术。
- 正向索引:就像一本书的目录,记录了 “第几页” 有哪些 “词”,查询时,你需要遍历所有文档,看哪个文档包含你的关键词,效率低下。
- 倒排索引:就像一本书的索引,记录了 “哪个词” 出现在 “第几页”,查询时,你直接查找关键词,就能立刻得到包含它的所有文档列表,速度极快。
Elasticsearch 在写入文档时,会构建一个倒排索引,将词项与包含该词项的文档列表关联起来。
第三部分:安装与启动
环境要求
- Java 8+:Elasticsearch 基于 Java 开发,需要安装 JDK。
- Linux / macOS / Windows:Linux 是最常见的服务器环境。
- 内存:建议至少 4GB 内存,生产环境需要更多。
安装 Elasticsearch
-
下载:从 Elasticsearch 官网 下载对应平台的压缩包。
-
解压:
tar -xzf elasticsearch-8.x.x-linux-x86_64.tar.gz cd elasticsearch-8.x.x/
-
启动:
# 前台启动,可以看到日志 ./bin/elasticsearch # 后台启动 ./bin/elasticsearch -d
注意:Elasticsearch 默认会绑定在
localhost:9200,并且从 Java 17 开始,它不再支持 root 用户启动,请使用普通用户启动。
安装 Kibana
Kibana 是 Elasticsearch 的官方可视化工具,提供了强大的数据探索、仪表盘和 Dev Tools 功能。
- 下载:从 Kibana 官网 下载。
- 解压:
tar -xzf kibana-8.x.x-linux-x86_64.tar.gz cd kibana-8.x.x/
- 配置:编辑
config/kibana.yml,确保elasticsearch.hosts指向你的 Elasticsearch 地址。# config/kibana.yml elasticsearch.hosts: ["http://localhost:9200"]
- 启动:
./bin/kibana
验证安装
打开浏览器,访问 http://localhost:5601,你应该能看到 Kibana 的欢迎页面。
在 Kibana 的 Dev Tools (开发者工具) 中,执行以下命令:
GET /
如果返回类似下面的 JSON,说明 Elasticsearch 运行正常:
{
"name" : "node-1",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "xxxxxxxx...",
"version" : {
"number" : "8.x.x",
...
},
"tagline" : "You Know, for Search"
}
第四部分:实战操作:使用 REST API
我们将通过 Kibana Dev Tools 来进行所有 API 操作,Dev Tools 提供了一个便捷的界面,可以自动补全和格式化 JSON。
CRUD 操作
假设我们想存储一些商品信息。
创建文档
向 products 索引中添加一个文档。_id 可以由 Elasticsearch 自动生成,也可以手动指定。
// POST /products/_doc
// 自动生成 ID
POST /products/_doc
{
"name": "iPhone 14 Pro",
"price": 7999,
"stock": 100,
"tags": ["手机", "苹果", "5G"]
}
// POST /products/_doc/1
// 手动指定 ID 为 1
POST /products/_doc/1
{
"name": "MacBook Pro 14",
"price": 14999,
"stock": 50,
"tags": ["笔记本", "苹果", "M2芯片"]
}
响应:
{
"_index": "products",
"_id": "1", // 或自动生成的 ID
"_version": 1,
"result": "created", // "created" 表示新建,"updated" 表示更新
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
读取文档
通过索引名和文档 ID 获取文档。
// GET /products/_doc/1 GET /products/_doc/1
响应:
{
"_index": "products",
"_id": "1",
"_version": 1,
"found": true,
"_source": { // 完整的文档内容
"name": "MacBook Pro 14",
"price": 14999,
"stock": 50,
"tags": ["笔记本", "苹果", "M2芯片"]
}
}
更新文档
更新有两种方式:替换 和 部分更新。
-
替换:相当于删除旧文档,创建一个新文档。
// PUT /products/_doc/1 PUT /products/_doc/1 { "name": "MacBook Pro 14 (M2芯片)", "price": 14999, "stock": 48, "tags": ["笔记本", "苹果", "M2芯片"] } -
部分更新:使用
script或doc参数,只更新指定的字段。推荐。// POST /products/_update/1 POST /products/_update/1 { "doc": { "stock": 45 } }
删除文档
// DELETE /products/_doc/1 DELETE /products/_doc/1
搜索入门
GET 请求搜索
直接对索引发起 GET 请求,会返回该索引下的所有文档。
// GET /products/_search GET /products/_search
query string 搜索
在 URL 的 q 参数中指定查询条件,简单快捷,但不灵活。
// 查找 name 中包含 "iPhone" 的文档 GET /products/_search?q=name:iPhone // 查找 name 中包含 "MacBook" 且 price 小于 15000 的文档 GET /products/_search?q=name:MacBook AND price:<15000
query DSL 搜索 (推荐)
这是 Elasticsearch 最强大、最灵活的查询方式,使用 JSON 格式的请求体来构建复杂的查询。
// POST /products/_search
POST /products/_search
{
"query": {
"match": { // match 查询用于全文搜索
"name": "iPhone"
}
}
}
第五部分:深入搜索:Query DSL
Query DSL 是 Elasticsearch 查询的核心,它使用 JSON 来定义查询。
搜索的基本结构
所有搜索请求的结构都类似:
POST /<index-name>/_search
{
"query": { // 查询子句,定义如何过滤文档
"your_query_type": {
"field": "value"
}
},
"from": 0, // 分页起始位置
"size": 10, // 返回文档数量
"sort": [ // 排序
{ "price": "desc" }
],
"aggs": { // 聚合,用于数据分析
"aggregation_name": {
"your_aggregation_type": {
"field": "field_name"
}
}
}
}
bool 查询:组合查询的利器
bool (boolean) 查询可以组合多个子查询,通过 must, should, filter, must_not 来实现复杂的逻辑。
must:必须 匹配,文档必须满足must下的所有条件。会计算相关性分数。filter:必须 匹配,文档必须满足filter下的所有条件。不计算分数,性能更好,结果会被缓存。should:应该 匹配,文档满足should下的条件越多,相关性分数越高,如果设置了minimum_should_match,则必须满足至少指定数量的条件。must_not:必须不 匹配,文档不能满足must_not下的任何条件。不计算分数。
示例:查找价格在 5000 到 10000 之间,且名称包含 "苹果" 或 "MacBook" 的商品,但不能是 "手机"。
POST /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "苹果" } }
],
"should": [
{ "match": { "name": "MacBook" } }
],
"filter": [
{ "range": { "price": { "gte": 5000, "lte": 10000 } } }
],
"must_not": [
{ "match": { "name": "手机" } }
],
"minimum_should_match": 1 // must 和 should 至少满足一个
}
}
}
其他常用查询
match:全文查询,会将查询字符串进行分词,然后去倒排索引中匹配,适用于text类型的字段。{ "match": { "description": "快速充电" } }term:精确值查询,不会对查询值进行分词,直接匹配倒排索引中的词项,适用于keyword类型的字段(如状态、标签)。{ "term": { "tags": "苹果" } }range:范围查询,用于数值、日期、字符串等。{ "range": { "price": { "gt": 5000, "lte": 10000 } } } // gt: >, gte: >=, lt: <, lte: <=wildcard:通配符查询。 匹配任意单个字符, 匹配任意多个字符。{ "wildcard": { "name": "iPho*" } }fuzzy:模糊查询,允许查询词与文档中的词有一定程度的差异(编辑距离)。{ "fuzzy": { "name": "iPhon" } } // 会匹配 "iPhone"
排序与分页
POST /products/_search
{
"query": {
"match_all": {} // 匹配所有文档
},
"from": 0, // 从第 0 条开始
"size": 10, // 返回 10 条
"sort": [
{ "price": "desc" }, // 按价格降序
{ "_score": "asc" } // 按相关性分数升序
]
}
聚合分析:从数据中提取洞察
聚合类似于 SQL 中的 GROUP BY 和 COUNT,但功能更强大。
- 桶聚合:对文档进行分组。
- 度量聚合:对桶内的文档进行计算(如求和、平均值、最大值等)。
示例:按品牌对商品进行分组,并计算每个品牌的商品数量和平均价格。
POST /products/_search
{
"size": 0, // 聚合查询通常不需要返回文档,设为 0 提高性能
"aggs": {
"group_by_brand": { // 聚合名称,自定义
"terms": { // 桶聚合类型:terms (按词项分组)
"field": "tags.keyword" // 使用 keyword 字段进行精确分组
},
"aggs": { // 嵌套聚合,对每个桶进行计算
"avg_price": { // 度量聚合名称
"avg": { "field": "price" } // 计算平均价格
}
}
}
}
}
响应:
{
...
"aggregations": {
"group_by_brand": {
"buckets": [
{
"key": "苹果",
"doc_count": 2, // 该桶中的文档数
"avg_price": { "value": 11499.0 } // 平均价格
},
{
"key": "三星",
"doc_count": 1,
"avg_price": { "value": 5999.0 }
}
]
}
}
}
第六部分:进阶主题
数据建模:Mapping
Mapping 定义了文档中每个字段的 数据类型、如何分词、是否被索引 等规则,它类似于关系数据库中的表结构。
-
动态映射:Elasticsearch 会自动根据文档内容猜测字段类型,方便,但可能不准确。
text:用于全文搜索,会被分词。keyword:用于精确匹配、排序、聚合,不会被分词。integer,long,date,boolean,object等。
-
静态/显式 Mapping:手动创建 Mapping,精确控制字段行为。推荐用于生产环境。
示例:为 products 索引创建一个显式 Mapping。
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text" // 全文搜索,可分词
},
"name_keyword": { // 常用技巧:同时定义 text 和 keyword 版本
"type": "keyword" // 用于精确匹配和聚合
},
"price": {
"type": "double"
},
"stock": {
"type": "integer"
},
"tags": {
"type": "keyword" // 标签通常是精确值,所以用 keyword
},
"create_date": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis" // 指定日期格式
}
}
}
}
分析器:分词与标准化
分析器是 将文本字符串转换为一系列词项 的过程,它由三部分组成:
- Character Filters (字符过滤器):在分词前处理字符串,如移除 HTML 标签 (
<html>) 或将&替换为and。 - Tokenizer (分词器):将字符串按规则切分成词项,标准分词器按非字母字符切分,并将字母转为小写。
- Token Filters (词元过滤器):在分词后处理词项,如移除停用词 (a, the, is)、同义词替换 (like -> love) 或词干提取 (running -> run)。
标准分析器 的工作流程:
"The QUICK brown foxes!" -> (字符过滤器) -> "The QUICK brown foxes!" -> (分词器) -> ["the", "quick", "brown", "foxes"] -> (词元过滤器) -> ["quick", "brown", "fox"]
自定义分析器:你可以组合不同的字符过滤器、分词器和词元过滤器来创建适合你业务场景的分析器。
索引模板与生命周期管理
- 索引模板:用于为新索引定义默认的
settings和mappings,当你创建一个符合某个模式(如logs-2025-*)的索引时,模板会自动应用。 - 索引生命周期管理:自动化索引的管理流程,可以定义一系列阶段,如 Hot (热)、Warm (温)、Cold (冷)、Delete (删除),在每个阶段,可以自动执行操作,如:
- Hot:索引活跃写入和查询。
- Warm:将索引移到较慢的存储,减少副本数量,只读查询。
- Cold:将索引归档到最便宜的存储。
- Delete:自动删除旧索引。
第七部分:生产环境与运维
集群健康状态
使用 cat health API 查看集群状态。
GET /_cat/health?v
状态:
green:所有主分片和副本分片都正常。yellow:所有主分片正常,但有副本分片未分配。red:有主分片未分配,数据丢失。
备份与恢复
- 快照:将索引或整个集群的数据备份到远程仓库(如 S3、HDFS)。
- 注册仓库。
PUT /_snapshot/my_backup { "type": "s3", "settings": { "bucket": "my-es-backups-bucket", "region": "us-west-1" } } - 创建快照。
PUT /_snapshot/my_backup/snapshot_1
- 恢复。
POST /_snapshot/my_backup/snapshot_1/_restore
- 注册仓库。
监控
- 监控 API:
_nodes/stats,_cluster/stats等。 - Elastic Stack 监控:使用 Metricbeat 收集 Elasticsearch 自身指标,并在 Kibana 中创建可视化仪表盘。
- X-Pack Monitoring:Elastic 官方提供的商业级监控解决方案。
性能调优简介
- 硬件:足够大的堆内存(通常不超过 31GB,使用 G1GC 垃圾回收器),SSD 硬盘。
- JVM 调优:合理设置
-Xms和-Xmx,通常设置为服务器物理内存的 50% 左右,且两者相等。 - 索引设计:合理的分片数量(每个分片大小在 10GB 到 50GB 之间),避免过度分片。
- 查询优化:使用
filter代替must,避免script查询,利用缓存。
第八部分:学习资源与总结
官方文档
- Elasticsearch 官方文档:最权威、最全面的学习资料,没有之一。
- Kibana 用户指南。
推荐书籍
- 《Elasticsearch 权威指南》:虽然是基于旧版本,但核心概念和思想依然非常经典,是很多人的入门启蒙书。
- 《Elasticsearch in Action》:结合实例,讲解如何在实际项目中使用 Elasticsearch。
社区与博客
- Elastic 官方博客:发布产品更新、最佳实践和技术文章。
- Stack Overflow:遇到问题时,先搜索这里。
- 国内社区:如思否、掘金等,也有很多优秀的 Elasticsearch 文章。
Elasticsearch 是一个功能极其强大的工具,但学习曲线也相对陡峭,掌握它的关键在于:
- 理解核心概念:集群、索引、文档、分片、倒排索引。
- 精通 Query DSL:
bool查询是你的瑞士军刀。 - 重视 Mapping 和 Analyzer:它们决定了你的数据如何被存储和搜索,是优化的基础。
- 动手实践:多在 Dev Tools 中尝试各种操作和查询,观察返回结果。
- 阅读官方文档:遇到任何问题,第一选择永远是官方文档。
从现在开始,选择一个你感兴趣的场景(比如分析你自己的日志文件),动手搭建一个 Elasticsearch 集群,然后尝试去索引、查询和分析它,祝你在 Elasticsearch 的世界里探索愉快!
