Elasticsearch 全栈教程:从入门到精通

目录

  1. 第一部分:初识 Elasticsearch

    elasticsearch 教程
    (图片来源网络,侵删)
    • 什么是 Elasticsearch?
    • 它能做什么?(典型应用场景)
    • 核心特点与优势
    • 与传统数据库的对比
  2. 第二部分:核心概念

    • 集群与节点
    • 索引
    • 文档
    • 分片与副本
    • 倒排索引
  3. 第三部分:安装与启动

    • 环境要求
    • 安装 Elasticsearch
    • 安装 Kibana (开发者必备工具)
    • 验证安装
  4. 第四部分:实战操作:使用 REST API

    • 交互工具:Kibana Dev Tools
    • CRUD 操作
      • 创建文档
      • 读取文档
      • 更新文档
      • 删除文档
    • 搜索入门
      • GET 请求搜索
      • query string 搜索
      • query DSL 搜索 (推荐)
  5. 第五部分:深入搜索:Query DSL

    elasticsearch 教程
    (图片来源网络,侵删)
    • 搜索的基本结构
    • bool 查询:组合查询的利器
      • must (必须匹配)
      • should (应该匹配,影响相关性)
      • filter (必须匹配,但不计算分数)
      • must_not (必须不匹配)
    • 其他常用查询
      • match (全文匹配)
      • term (精确值匹配)
      • range (范围查询)
      • wildcard (通配符查询)
      • fuzzy (模糊查询)
    • 排序与分页
    • 聚合分析:从数据中提取洞察
      • 桶聚合
      • 度量聚合
  6. 第六部分:进阶主题

    • 数据建模:Mapping
      • 动态映射 vs. 静态映射
      • 常用数据类型
      • 自定义 Mapping
    • 分析器:分词与标准化
      • 什么是分析器?
      • 标准分析器 工作流程
      • 内置分析器
      • 自定义分析器
    • 索引模板与生命周期管理
    • 安全:基础认证与 TLS
  7. 第七部分:生产环境与运维

    • 集群健康状态
    • 备份与恢复
    • 监控
    • 性能调优简介
  8. 第八部分:学习资源与总结

    • 官方文档
    • 推荐书籍
    • 社区与博客

第一部分:初识 Elasticsearch

什么是 Elasticsearch?

Elasticsearch 是一个基于 Lucene 库构建的 开源、分布式、RESTful 风格搜索引擎,它被设计用于处理大规模数据的实时搜索、分析和存储。

elasticsearch 教程
(图片来源网络,侵删)

你可以把它想象成一个 “超级数据库”,但它不擅长事务性操作(比如银行转账),而是极其擅长 “快速查找和分析”

它能做什么?(典型应用场景)

  1. 网站搜索:为电商、新闻、博客等网站提供强大的全文检索功能。
  2. 日志分析:收集、存储和分析来自服务器、应用、网络设备的海量日志,是 ELK/EFK 技术栈的核心,常用于实时监控、故障排查和安全审计。
  3. 指标监控:存储和查询时间序列数据,用于系统性能监控和可视化。
  4. 安全分析:通过搜索和分析安全事件日志,检测异常行为和潜在威胁。
  5. 商业智能:对业务数据进行聚合分析,生成报表和仪表盘。

核心特点与优势

  • 分布式:数据被分散存储在多个节点上,易于水平扩展,处理 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

  1. 下载:从 Elasticsearch 官网 下载对应平台的压缩包。

  2. 解压

    tar -xzf elasticsearch-8.x.x-linux-x86_64.tar.gz
    cd elasticsearch-8.x.x/
  3. 启动

    # 前台启动,可以看到日志
    ./bin/elasticsearch
    # 后台启动
    ./bin/elasticsearch -d

    注意:Elasticsearch 默认会绑定在 localhost:9200,并且从 Java 17 开始,它不再支持 root 用户启动,请使用普通用户启动。

安装 Kibana

Kibana 是 Elasticsearch 的官方可视化工具,提供了强大的数据探索、仪表盘和 Dev Tools 功能。

  1. 下载:从 Kibana 官网 下载。
  2. 解压
    tar -xzf kibana-8.x.x-linux-x86_64.tar.gz
    cd kibana-8.x.x/
  3. 配置:编辑 config/kibana.yml,确保 elasticsearch.hosts 指向你的 Elasticsearch 地址。
    # config/kibana.yml
    elasticsearch.hosts: ["http://localhost:9200"]
  4. 启动
    ./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芯片"]
    }
  • 部分更新:使用 scriptdoc 参数,只更新指定的字段。推荐

    // 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 BYCOUNT,但功能更强大。

  • 桶聚合:对文档进行分组。
  • 度量聚合:对桶内的文档进行计算(如求和、平均值、最大值等)。

示例:按品牌对商品进行分组,并计算每个品牌的商品数量和平均价格。

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" // 指定日期格式
      }
    }
  }
}

分析器:分词与标准化

分析器是 将文本字符串转换为一系列词项 的过程,它由三部分组成:

  1. Character Filters (字符过滤器):在分词前处理字符串,如移除 HTML 标签 (<html>) 或将 & 替换为 and
  2. Tokenizer (分词器):将字符串按规则切分成词项,标准分词器按非字母字符切分,并将字母转为小写。
  3. Token Filters (词元过滤器):在分词后处理词项,如移除停用词 (a, the, is)、同义词替换 (like -> love) 或词干提取 (running -> run)。

标准分析器 的工作流程: "The QUICK brown foxes!" -> (字符过滤器) -> "The QUICK brown foxes!" -> (分词器) -> ["the", "quick", "brown", "foxes"] -> (词元过滤器) -> ["quick", "brown", "fox"]

自定义分析器:你可以组合不同的字符过滤器、分词器和词元过滤器来创建适合你业务场景的分析器。

索引模板与生命周期管理

  • 索引模板:用于为新索引定义默认的 settingsmappings,当你创建一个符合某个模式(如 logs-2025-*)的索引时,模板会自动应用。
  • 索引生命周期管理:自动化索引的管理流程,可以定义一系列阶段,如 Hot (热)Warm (温)Cold (冷)Delete (删除),在每个阶段,可以自动执行操作,如:
    • Hot:索引活跃写入和查询。
    • Warm:将索引移到较慢的存储,减少副本数量,只读查询。
    • Cold:将索引归档到最便宜的存储。
    • Delete:自动删除旧索引。

第七部分:生产环境与运维

集群健康状态

使用 cat health API 查看集群状态。

GET /_cat/health?v

状态

  • green:所有主分片和副本分片都正常。
  • yellow:所有主分片正常,但有副本分片未分配。
  • red:有主分片未分配,数据丢失。

备份与恢复

  • 快照:将索引或整个集群的数据备份到远程仓库(如 S3、HDFS)。
    1. 注册仓库。
      PUT /_snapshot/my_backup
      {
        "type": "s3",
        "settings": {
          "bucket": "my-es-backups-bucket",
          "region": "us-west-1"
        }
      }
    2. 创建快照。
      PUT /_snapshot/my_backup/snapshot_1
    3. 恢复。
      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 权威指南》:虽然是基于旧版本,但核心概念和思想依然非常经典,是很多人的入门启蒙书。
  • 《Elasticsearch in Action》:结合实例,讲解如何在实际项目中使用 Elasticsearch。

社区与博客

  • Elastic 官方博客:发布产品更新、最佳实践和技术文章。
  • Stack Overflow:遇到问题时,先搜索这里。
  • 国内社区:如思否、掘金等,也有很多优秀的 Elasticsearch 文章。

Elasticsearch 是一个功能极其强大的工具,但学习曲线也相对陡峭,掌握它的关键在于:

  1. 理解核心概念:集群、索引、文档、分片、倒排索引。
  2. 精通 Query DSLbool 查询是你的瑞士军刀。
  3. 重视 Mapping 和 Analyzer:它们决定了你的数据如何被存储和搜索,是优化的基础。
  4. 动手实践:多在 Dev Tools 中尝试各种操作和查询,观察返回结果。
  5. 阅读官方文档:遇到任何问题,第一选择永远是官方文档。

从现在开始,选择一个你感兴趣的场景(比如分析你自己的日志文件),动手搭建一个 Elasticsearch 集群,然后尝试去索引、查询和分析它,祝你在 Elasticsearch 的世界里探索愉快!