从零开始学习 Elasticsearch:超详细入门教程
引言:搜索的革命与 Elasticsearch 的崛起
在当今信息爆炸的时代,如何快速、准确地找到所需的信息成为了一个巨大的挑战。无论是网站内部的商品搜索、日志分析平台的数据查询、还是大数据应用的实时分析,传统的数据库系统往往难以满足需求。它们虽然擅长结构化数据的存储和精确查找,但在处理非结构化或半结构化数据、进行全文搜索、实现近实时查询以及应对海量数据和高并发方面显得力不从心。
正是在这样的背景下,像 Elasticsearch 这样的分布式搜索与分析引擎应运而生。Elasticsearch 不仅仅是一个强大的搜索引擎,它还是一个高度可伸缩、易于部署、拥有近乎实时查询能力的分布式系统。凭借其强大的全文搜索能力、灵活的 JSON 文档模型、以及为分析而生的聚合(Aggregations)功能,Elasticsearch 在日志分析(著名的 ELK/ECK Stack)、实时监控、应用程序搜索、企业搜索等众多领域得到了广泛应用。
如果你对 Elasticsearch 一无所知,甚至连“搜索”以外的概念都觉得陌生,没关系!本文将带你从零开始,一步步深入理解 Elasticsearch 的核心概念、工作原理,并通过实际操作带你走完入门的必经之路。无论你是一名开发者、数据分析师,还是对技术充满好奇的探索者,这篇超详细的入门教程都将是你学习 Elasticsearch 的绝佳起点。
我们将覆盖以下关键内容:
- Elasticsearch 是什么?为什么选择它?
- 核心概念详解:理解 Elasticsearch 的基石
- 动手实践:安装与启动 Elasticsearch
- 基本操作:索引、获取、搜索、更新和删除文档
- 深入理解:映射 (Mapping) 与分析 (Analysis)
- 简单实例演示:构建一个迷你图书搜索
- 超越入门:接下来可以学什么?
准备好了吗?让我们一起开启 Elasticsearch 的学习之旅!
1. Elasticsearch 是什么?为什么选择它?
1.1 Elasticsearch 的定义
Elasticsearch (通常缩写为 ES) 是一个基于 Apache Lucene 构建的开源、分布式、RESTful 风格的搜索和分析引擎。它的核心优势在于:
- 分布式 (Distributed): 数据可以分布在多个节点上,天然支持横向扩展,轻松应对大数据量。
- RESTful API: 提供简单易用的 HTTP RESTful 接口,可以使用几乎任何编程语言与之交互。
- 近实时 (Near Real-time – NRT): 文档从索引到可搜索之间只有短暂的延迟(通常在1秒内)。
- 可扩展性 (Scalability): 轻松通过添加节点来扩展集群的处理能力和存储容量。
- 高可用性 (High Availability): 通过副本机制保证数据的冗余,即使部分节点故障也能继续提供服务。
- 速度 (Speed): 基于倒排索引等技术,查询速度极快,尤其擅长全文搜索。
1.2 Elasticsearch 的用途与优势
为什么要在众多的数据存储和查询方案中选择 Elasticsearch?
- 强大的全文搜索能力: 基于 Lucene 的强大搜索库,支持各种复杂的查询,如模糊查询、短语查询、高亮显示、排序、过滤等,并能处理同义词、词干提取等语言相关的搜索需求。
- 实时数据分析: 配合 Kibana 等工具,可以对海量数据进行近实时的聚合分析,生成各种统计报表、图表和仪表盘,广泛应用于日志分析、指标监控等场景。
- 灵活的 JSON 文档模型: 数据以 JSON 文档形式存储,不需要预定义严格的表结构(但映射很重要,后面会讲),更适合存储和处理半结构化数据。
- 易于使用和集成: RESTful API 使得与各种应用程序集成变得非常简单。
- 生态系统完整: Elasticsearch 是 Elastic Stack (ELK/ECK) 的核心组件,与 Logstash (数据采集)、Kibana (数据可视化与管理) 和 Beats (轻量级数据采集器) 无缝集成,提供一站式解决方案。
- 高吞吐量: 能够处理大量的索引和搜索请求。
简而言之,当你需要对大量非结构化或半结构化数据进行快速、灵活的全文搜索和近实时分析时,Elasticsearch 通常是首选的解决方案。
2. 核心概念详解:理解 Elasticsearch 的基石
在开始动手操作之前,理解 Elasticsearch 的几个核心概念至关重要。它们构成了 Elasticsearch 的基础架构和数据模型。
2.1 集群 (Cluster)
- 定义: 一个集群由一个或多个节点组成,它们共享一个唯一的集群名称 (默认是
elasticsearch
)。集群提供了分布式索引和搜索能力。 - 作用: 实现高可用性、可伸缩性和数据分发。当集群中有多个节点时,即使部分节点宕机,整个集群仍能继续工作(取决于副本设置),并且可以通过增加节点来提升处理能力。
- 健康状态: 集群有三种健康状态:
- 绿色 (Green): 所有主分片和副本分片都正常分配,集群健康。
- 黄色 (Yellow): 所有主分片都正常分配,但至少有一个副本分片未能正常分配。集群功能完整,但存在数据冗余风险。
- 红色 (Red): 至少有一个主分片未能正常分配。部分数据不可用,集群功能不完整。
2.2 节点 (Node)
- 定义: 一个节点是 Elasticsearch 集群中的一个独立运行实例。通常,一个节点运行在一台物理服务器或虚拟机上,但也可以在同一台机器上运行多个节点用于测试。
- 类型 (简化):
- 主节点 (Master Node): 负责管理集群的元数据,如索引的创建/删除、分片分配等。一个集群通常只有一个主节点负责决策,但可以有多个节点具备成为主节点的资格(Master-eligible nodes),以便在当前主节点故障时进行选举。
- 数据节点 (Data Node): 负责存储数据和执行数据相关的操作,如索引、搜索、聚合等。这是最常见的节点类型。
- (对于初学者,可以暂时理解节点主要分为负责管理的和负责存储数据的即可,更复杂的节点类型如 Ingest Node, Coordinating Node 等可以后续再学)。
- 发现: 节点通过配置或网络多播(不推荐生产环境)相互发现并加入同一个集群。
2.3 索引 (Index)
- 定义: 索引是 Elasticsearch 中存储相似类型文档的集合。它可以类比于关系型数据库中的“数据库”或“表”(尽管这个类比不完全准确,后面会解释)。
- 作用: 索引定义了文档如何被存储和检索。一个索引通常包含具有相似结构(或至少是相似处理方式)的文档。例如,你可以创建一个
logs
索引来存储日志数据,一个products
索引来存储商品信息。 - 命名: 索引名称必须是小写字母,不能包含
\
、/
、*
、?
、"
、<
、>
、|
、(空格)、
,
、#
。 - 分片与副本: 每个索引被分成一个或多个分片,并且每个分片可以有一个或多个副本。
2.4 文档 (Document)
- 定义: 文档是 Elasticsearch 中可被索引的最小单位数据。它是一个 JSON 格式的对象,包含一系列字段(Key-Value 对)。
- 类比: 可以类比于关系型数据库中的“行”(Row)。
- ID: 每个文档在索引中都有一个唯一的 ID。你可以自己指定 ID,或者让 Elasticsearch 自动生成。
- 无模式 (Schema-less / Dynamic Mapping): 默认情况下,Elasticsearch 具有动态映射能力。当你索引一个新文档时,如果之前没有定义过该字段的类型,Elasticsearch 会根据字段的值自动推断字段类型并创建对应的映射。虽然这提供了灵活性,但在生产环境中通常建议提前定义好映射 (Explicit Mapping),以确保数据的一致性和搜索的准确性。
2.5 字段 (Field)
- 定义: 文档中的一个键值对,例如
{"name": "张三", "age": 30}
中的name
和age
就是字段。 - 类型: 每个字段都有一个类型,例如
text
,keyword
,integer
,boolean
,date
,object
,geo_point
等。字段类型决定了 Elasticsearch 如何索引、存储和搜索该字段的值。理解字段类型尤其是text
和keyword
的区别是 Elasticsearch 入门的关键!
2.6 映射 (Mapping)
- 定义: 映射描述了索引中文档及其字段的结构和数据类型,以及如何索引和存储这些字段。
- 作用: 映射告诉 Elasticsearch 每个字段是字符串、数字、布尔值还是日期等等,以及如何对字符串字段进行分词处理(分析)。
- 重要性: 映射直接影响搜索结果的准确性和字段的处理方式。例如,一个字段被映射为
text
类型,会被分析器处理(如分词),适合全文搜索;而被映射为keyword
类型则不会被分析,适合精确匹配、排序和聚合。
2.7 分析 (Analysis)
- 定义: 分析是将文本字段的值转换为可搜索的词项 (terms) 的过程。
- 过程: 通常涉及三个步骤:
- 字符过滤器 (Character Filters): 在文本分词之前,对原始文本进行处理,如去除 HTML 标签、将特殊字符转换为普通字符等。
- 分词器 (Tokenizer): 将文本分解成一系列独立的词项(tokens)。例如,标准分词器会按空格和标点符号分割文本。
- 词项过滤器 (Token Filters): 对分词器产生的词项进行进一步处理,如转换为小写、去除停用词(stopwords)、词干提取(stemming)等。
- 重要性: 分析过程决定了哪些词项会被存储在倒排索引中,从而直接影响到搜索时哪些查询词能够匹配到文档。
2.8 分片 (Shard)
- 定义: 分片是将一个索引水平分割的结果。每个分片都是一个独立的 Lucene 索引。
- 作用:
- 扩展性: 允许将一个大型索引的数据分布到多个节点上,突破单个节点的硬件限制。
- 并行性: 允许在多个分片上并行执行搜索请求,提高搜索速度。
- 类型:
- 主分片 (Primary Shard): 存储索引数据的原始副本。当索引文档时,文档首先被发送到其对应的主分片。一个文档只能属于一个主分片。
- 副本分片 (Replica Shard): 主分片的复制。副本分片提供了数据冗余(高可用性),并在搜索时分担主分片的负载(读取扩展)。副本分片永远不会分配在与其对应主分片相同的节点上。
2.9 副本 (Replica)
- 定义: 副本分片是对主分片的拷贝。
- 作用:
- 高可用性: 当主分片所在的节点故障时,副本分片可以被提升为新的主分片,保证数据不丢失和服务的连续性。
- 读性能扩展: 搜索请求可以由主分片或其任意副本分片处理,增加副本数量可以提高集群处理并发搜索请求的能力。
- 数量: 可以为每个主分片设置零个或多个副本。副本数量可以在索引创建后动态调整。
概念关系总结:
一个 集群 由一个或多个 节点 组成。数据存储在 索引 中。每个 索引 被分成多个 主分片,每个 主分片 可以有零到多个 副本分片。分片(主分片或副本分片)分配在不同的 节点 上。索引中的数据是 文档,每个 文档 是一个 JSON 对象,包含 字段。 映射 定义了文档和字段的结构及处理方式,尤其是文本字段会经过 分析 过程生成可搜索的词项。
3. 动手实践:安装与启动 Elasticsearch
学习任何技术,最好的方式就是动手实践。我们将介绍最简单的方式来安装和启动 Elasticsearch。
3.1 前置条件:Java 环境
Elasticsearch 是基于 Java 开发的,因此你的系统上需要安装 Java 环境。Elasticsearch 通常对 Java 版本有特定要求,请查阅你打算安装的 Elasticsearch 版本的官方文档,确认所需的 Java 版本。通常建议使用 Oracle JDK 或 OpenJDK。
可以通过在终端运行 java -version
来检查 Java 是否已安装及版本。
3.2 下载 Elasticsearch
访问 Elastic 官方网站 (https://www.elastic.co/cn/downloads/elasticsearch) 下载适合你操作系统的 Elasticsearch 安装包(zip 或 tar.gz)。选择一个较新的稳定版本进行学习。
3.3 安装与启动 (以 zip/tar.gz 包为例)
- 解压文件: 将下载的压缩包解压到你选择的目录。例如,解压到
~/elasticsearch-8.x.x
。 - 进入目录: 打开终端或命令行工具,进入解压后的 Elasticsearch 目录。
bash
cd ~/elasticsearch-8.x.x - 配置(可选,但建议):
- 默认配置通常可以在本地单节点环境下工作。
- 修改
config/elasticsearch.yml
文件可以配置集群名称、节点名称、数据存储路径、网络绑定等。对于初学者,可以暂时保留默认配置,除非遇到网络绑定问题(默认只绑定 localhost)。如果需要外部访问,可以修改network.host: 0.0.0.0
(注意安全风险,生产环境需配置防火墙)。 - 重要: Elasticsearch 8.x 版本默认启用安全认证 (TLS and basic authentication)。首次启动时会生成一个弹性用户密码和 enroll token。请务必记住这些信息!或者,你可以在
config/elasticsearch.yml
中设置xpack.security.enabled: false
来禁用安全认证(仅用于本地学习或非敏感环境,生产环境强烈建议启用)。为了简化入门,本文后续操作将假设你已禁用安全认证或知道如何处理认证。建议初学者在本地先禁用安全认证进行学习。
- 启动 Elasticsearch: 在终端中运行启动脚本。
- Linux/macOS:
bash
./bin/elasticsearch - Windows:
batch
.\bin\elasticsearch.bat - 启动过程中会输出大量日志信息。看到类似
started
的字样,并且没有错误信息,说明启动成功。Elasticsearch 默认运行在 9200 端口。
- Linux/macOS:
- 验证启动: 打开另一个终端窗口,使用 curl 命令(或浏览器访问)验证 Elasticsearch 是否正在运行。
bash
curl http://localhost:9200
如果看到返回了一个包含集群名称、版本信息等的 JSON 响应,恭喜你,Elasticsearch 已经成功运行!
3.4 安装 Kibana (推荐)
Kibana 是 Elasticsearch 的官方配套工具,提供了一个友好的 Web 界面来管理、监控 Elasticsearch 集群,以及查询、分析和可视化数据。强烈建议安装 Kibana。
- 下载 Kibana: 访问 Elastic 官方网站 (https://www.elastic.co/cn/downloads/kibana) 下载与你 Elasticsearch 版本匹配的 Kibana 安装包。
- 解压文件: 将下载的压缩包解压到你选择的目录。
- 配置 Kibana: 进入 Kibana 目录下的
config
文件夹,修改kibana.yml
文件。主要需要配置elasticsearch.hosts
,确保它指向你的 Elasticsearch 实例。如果 Elasticsearch 运行在localhost:9200
且禁用了安全认证,默认配置通常无需修改。如果 Elasticsearch 启用了安全认证,你需要配置 Kibana 连接时使用的认证信息。 - 启动 Kibana: 在终端中进入 Kibana 目录,运行启动脚本。
- Linux/macOS:
bash
./bin/kibana - Windows:
batch
.\bin\kibana.bat - Kibana 默认运行在 5601 端口。
- Linux/macOS:
- 访问 Kibana: 打开浏览器,访问
http://localhost:5601
。你应该能看到 Kibana 的欢迎页面。在 Kibana 中,你可以使用 Dev Tools (开发工具) 来执行 Elasticsearch 的 RESTful API 请求,这比使用curl
命令方便得多。后续的操作示例将主要在 Dev Tools 中进行。
4. 基本操作:索引、获取、搜索、更新和删除文档
Elasticsearch 的主要交互方式是通过 RESTful API。我们将使用 Kibana 的 Dev Tools (控制台) 来执行这些操作。在 Kibana 页面左侧导航栏找到 “Management” 或 “Management and Administration” (取决于版本),然后点击 “Dev Tools” (开发工具)。
Dev Tools 界面左侧是你输入 API 请求的地方,右侧是响应结果。
4.1 索引文档 (Indexing Documents)
索引文档是将数据添加到 Elasticsearch 的过程。
-
自动生成 ID:
json
POST /my_index/_doc
{
"title": "Elasticsearch 权威指南",
"author": "Elastic",
"publish_date": "2015-02-01",
"price": 59.90,
"tags": ["搜索", "数据库", "分布式"]
}POST /<index>/_doc
: 使用 HTTP POST 请求,路径指定要索引的索引名称 (my_index
) 和文档类型 (_doc
,在 Elasticsearch 7.x 及以后版本,_doc
是推荐的文档类型)。- 请求体是一个 JSON 对象,代表要索引的文档。
- Elasticsearch 会为这个文档自动生成一个唯一的 ID,并在响应中返回。
- 如果
my_index
不存在,Elasticsearch 会自动创建它(并使用动态映射推断字段类型)。
-
指定 ID:
json
PUT /my_index/_doc/1
{
"title": "深入理解 Elasticsearch",
"author": "某技术作者",
"publish_date": "2019-08-15",
"price": 88.00,
"tags": ["搜索", "分布式", "技术"]
}PUT /<index>/_doc/<_id>
: 使用 HTTP PUT 请求,路径指定索引名称 (my_index
)、文档类型 (_doc
) 和你指定的文档 ID (1
)。- 如果 ID
1
的文档已存在,这个操作会替换(覆盖)现有文档。
响应示例 (自动生成 ID):
json
{
"_index": "my_index",
"_id": "某个自动生成的Base64字符串",
"_version": 1,
"result": "created", // 或 "updated" 如果是覆盖
"_seq_no": 0,
"_primary_term": 1
}
result
字段会告诉你操作是创建 (created
) 还是更新 (updated
)。_version
是文档的版本号,每次修改都会增加。_seq_no
和 _primary_term
是用于并发控制的内部字段。
4.2 获取文档 (Getting Documents)
通过文档 ID 可以获取特定文档的内容。
json
GET /my_index/_doc/1
* GET /<index>/_doc/<_id>
: 使用 HTTP GET 请求,指定索引名称和文档 ID。
响应示例:
json
{
"_index": "my_index",
"_id": "1",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true, // 表示文档是否存在
"_source": { // 文档的原始内容
"title": "深入理解 Elasticsearch",
"author": "某技术作者",
"publish_date": "2019-08-15",
"price": 88.00,
"tags": ["搜索", "分布式", "技术"]
}
}
_source
字段包含了索引时提交的原始 JSON 文档。
4.3 搜索文档 (Searching Documents)
搜索是 Elasticsearch 的核心功能。通过 _search
端点进行。
-
搜索所有文档:
json
GET /my_index/_search
{
"query": {
"match_all": {}
}
}GET /<index>/_search
: 对指定索引执行搜索请求。- 请求体是搜索请求体,使用 Elasticsearch Query DSL (Domain Specific Language)。
match_all
查询是最简单的查询,匹配索引中的所有文档。
-
基于字段的匹配查询 (Match Query): 搜索特定字段中包含某个词项的文档。
json
GET /my_index/_search
{
"query": {
"match": {
"title": "Elasticsearch"
}
}
}"match": {"title": "Elasticsearch"}
: 表示在title
字段中搜索包含词项 “Elasticsearch” 的文档。这里的 “Elasticsearch” 会经过字段对应的分析器处理。
-
响应示例 (搜索):
json
{
"took": 3, // 查询执行耗时(毫秒)
"timed_out": false, // 是否超时
"_shards": { // 关于分片的信息
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": { // 搜索结果集
"total": { // 匹配到的文档总数
"value": 2,
"relation": "eq" // eq 表示精确计数,gte 表示大于等于
},
"max_score": 0.6931472, // 最高得分
"hits": [ // 匹配到的文档列表(默认返回前10个)
{
"_index": "my_index",
"_id": "某个自动生成的Base64字符串",
"_score": 0.6931472, // 文档得分,越高越相关
"_source": {
"title": "Elasticsearch 权威指南",
"author": "Elastic",
"publish_date": "2015-02-01",
"price": 59.90,
"tags": ["搜索", "数据库", "分布式"]
}
},
{
"_index": "my_index",
"_id": "1",
"_score": 0.2876821,
"_source": {
"title": "深入理解 Elasticsearch",
"author": "某技术作者",
"publish_date": "2019-08-15",
"price": 88.00,
"tags": ["搜索", "分布式", "技术"]
}
}
// ... 更多结果
]
}
}
搜索结果的核心在hits
部分。hits.total
告诉你匹配到的文档总数,hits.hits
是一个数组,包含了实际返回的文档。每个返回的文档包括_index
,_id
,_score
(相关性得分) 和_source
(文档内容)。
4.4 更新文档 (Updating Documents)
Elasticsearch 的更新操作不是在原地修改文档,而是先标记旧文档为删除,然后索引一个包含修改内容的新文档。你可以选择完全替换文档,或者进行部分更新。
-
部分更新 (推荐): 使用
_update
端点,只提交需要修改的字段。
json
POST /my_index/_update/1
{
"doc": {
"price": 99.00
}
}POST /<index>/_update/<_id>
: 对指定 ID 的文档进行更新。- 请求体中,
"doc": {...}
表示要合并到现有文档中的字段。Elasticsearch 会将现有文档的字段与doc
中的字段合并,生成新文档进行索引。
-
完全替换 (同指定 ID 索引):
json
PUT /my_index/_doc/1
{
"title": "深入理解 Elasticsearch - 第二版", // 修改了标题
"author": "某技术作者",
"publish_date": "2022-10-01", // 修改了发布日期
"price": 99.00, // 修改了价格
"tags": ["搜索", "分布式", "技术", "更新"] // 修改了标签
}- 使用
PUT
方法向/my_index/_doc/1
提交完整的新文档内容,会完全替换 ID 为1
的现有文档。
- 使用
4.5 删除文档 (Deleting Documents)
通过文档 ID 删除特定文档。
json
DELETE /my_index/_doc/1
* DELETE /<index>/_doc/<_id>
: 使用 HTTP DELETE 请求,指定索引名称和文档 ID。
响应示例:
json
{
"_index": "my_index",
"_id": "1",
"_version": 2, // 版本号增加
"result": "deleted",
"_seq_no": 1,
"_primary_term": 1
}
result
字段为 deleted
表示删除成功。
4.6 删除索引 (Deleting Index)
删除整个索引及其包含的所有文档和元数据。这是一个危险的操作,数据将无法恢复!
json
DELETE /my_index
* DELETE /<index>
: 使用 HTTP DELETE 请求,指定要删除的索引名称。
响应示例:
json
{
"acknowledged": true // 表示请求已被集群接受并处理
}
通过上述基本操作,你已经学会了如何在 Elasticsearch 中进行数据的增删改查(CRUD)操作。然而,要真正发挥 Elasticsearch 的威力,理解数据的索引方式——即映射 (Mapping) 和分析 (Analysis)——至关重要。
5. 深入理解:映射 (Mapping) 与分析 (Analysis)
前面提到,映射定义了字段的数据类型和处理方式,而分析是将文本转换为可搜索词项的过程。这两者紧密关联,直接影响搜索的相关性和准确性。
5.1 映射 (Mapping)
虽然 Elasticsearch 支持动态映射,但在生产环境中显式定义映射是更好的实践,它可以:
- 确保数据类型准确: 避免 Elasticsearch 误判字段类型(例如把全是数字的字符串字段识别为
long
而不是keyword
)。 - 控制文本分析: 精确控制哪些字段需要分词 (
text
),哪些不需要 (keyword
),以及使用哪种分析器。 - 优化存储和查询性能: 不同的数据类型有不同的存储和索引方式。
查看现有映射:
json
GET /my_index/_mapping
* GET /<index>/_mapping
: 获取指定索引的当前映射信息。
手动创建索引并定义映射:
在索引任何文档之前,你可以先创建索引并定义其映射。
json
PUT /my_books
{
"mappings": {
"properties": {
"title": {
"type": "text", // 定义为文本类型,会被分析
"analyzer": "ik_smart" // 可选:指定一个中文分词器(需要安装插件)
},
"author": {
"type": "keyword" // 定义为关键词类型,不会被分析,适合精确匹配或排序
},
"publish_date": {
"type": "date", // 定义为日期类型
"format": "yyyy-MM-dd" // 指定日期格式
},
"price": {
"type": "float" // 定义为浮点数类型
},
"tags": {
"type": "keyword" // 定义为关键词类型数组
},
"description": {
"type": "text", // 另一个文本字段
"analyzer": "ik_max_word" // 可选:指定一个中文分词器
}
}
},
"settings": { // 可选:定义索引的设置,如分片数、副本数
"index": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}
}
* PUT /<index>
: 使用 PUT 请求创建索引。
* 请求体包含 mappings
和可选的 settings
。
* mappings.properties
中定义了每个字段的名称和类型。
* text
vs keyword
:
* text
: 适用于需要进行全文搜索的文本,如文章内容、标题描述等。存储时会被分词处理,搜索时输入的查询词也会被分词,然后匹配词项。
* keyword
: 适用于不需要分词的精确值,如人名、地名、标签、商品ID、状态码等。存储和搜索时按完整字符串匹配。适合用于过滤、排序和聚合。
5.2 分析 (Analysis)
分析器 (Analyzer) 是由字符过滤器、分词器和词项过滤器组成的。Elasticsearch 内置了许多分析器,如 standard
(默认)、simple
、whitespace
等。对于中文、日文、韩文等语言,通常需要安装第三方分词插件(如 ik-analyzer
、jieba
等),因为默认分析器对这些语言的支持不够好。
-
测试分析器:
可以使用_analyze
API 测试某个文本经过特定分析器处理后的结果。json
GET /_analyze
{
"analyzer": "standard",
"text": "Quick Brown Fox Jumps over the Lazy Dog."
}
响应会显示分词后的词项列表:["quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"]
(注意都变成了小写)。如果你安装了
ik-analyzer
插件,可以测试中文分词:
json
GET /_analyze
{
"analyzer": "ik_smart",
"text": "中华人民共和国国歌"
}
响应(使用 ik_smart)可能包含:["中华人民共和国", "中华人民", "共和国", "国歌"]
json
GET /_analyze
{
"analyzer": "ik_max_word",
"text": "中华人民共和国国歌"
}
响应(使用 ik_max_word,更细粒度)可能包含:["中华人民共和国", "中华人民", "中华", "华人", "人民", "共和", "共和国", "国歌"]
-
分析器与映射的关系: 在映射中,你可以为
text
字段指定一个分析器 (analyzer
参数)。如果在映射中没有指定,将使用索引的默认分析器(通常是standard
)。搜索时,查询文本默认也会使用字段对应的分析器进行处理,然后再去倒排索引中查找匹配的词项。
掌握映射和分析是编写有效搜索查询和获得准确搜索结果的关键。
6. 简单实例演示:构建一个迷你图书搜索
现在,让我们把学到的知识串联起来,构建一个简单的图书搜索应用。
-
创建索引并定义映射: 我们需要一个
books
索引,包含书名 (title)、作者 (author)、出版日期 (publish_date)、价格 (price) 和标签 (tags) 等字段。
json
PUT /books
{
"mappings": {
"properties": {
"title": {
"type": "text"
// 如果安装了中文分词器,可以加上 "analyzer": "ik_smart"
},
"author": {
"type": "keyword"
},
"publish_date": {
"type": "date",
"format": "yyyy-MM-dd"
},
"price": {
"type": "float"
},
"tags": {
"type": "keyword"
},
"description": {
"type": "text"
// 如果安装了中文分词器,可以加上 "analyzer": "ik_smart"
}
}
},
"settings": {
"index": {
"number_of_shards": 1,
"number_of_replicas": 1
}
}
}
执行上述命令创建books
索引。 -
索引一些图书文档:
“`json
POST /books/_doc/101
{
“title”: “Elasticsearch: The Definitive Guide”,
“author”: “Clinton Gormley”,
“publish_date”: “2015-02-01”,
“price”: 49.99,
“tags”: [“elasticsearch”, “search”, “guide”],
“description”: “A comprehensive guide to Elasticsearch.”
}POST /books/_doc/102
{
“title”: “Learning Elasticsearch 8.x”,
“author”: “Bradford Manning”,
“publish_date”: “2022-05-10”,
“price”: 55.50,
“tags”: [“elasticsearch”, “learning”, “8.x”],
“description”: “Learn the latest features of Elasticsearch 8.x.”
}POST /books/_doc/103
{
“title”: “深入浅出 Elasticsearch”,
“author”: “萧田国”,
“publish_date”: “2017-09-01”,
“price”: 79.00,
“tags”: [“elasticsearch”, “中文”, “教程”],
“description”: “一本很好的中文 Elasticsearch 入门书籍。”
}POST /books/_doc/104
{
“title”: “Clean Code”,
“author”: “Robert C. Martin”,
“publish_date”: “2008-08-01”,
“price”: 65.00,
“tags”: [“programming”, “clean code”, “软件工程”],
“description”: “A handbook of agile software craftsmanship.”
}
``
books` 索引中。
逐个执行上述命令,将四本图书索引到 -
执行搜索查询:
-
搜索包含 “Elasticsearch” 的图书 (在 title 或 description 字段,取决于你的映射和分析器):
json
GET /books/_search
{
"query": {
"multi_match": { // 使用 multi_match 可以在多个字段中搜索
"query": "Elasticsearch",
"fields": ["title", "description"]
}
}
}
你应该能搜到 ID 为 101, 102, 103 的图书。 -
精确搜索作者为 “Robert C. Martin” 的图书 (author 是 keyword 类型):
json
GET /books/_search
{
"query": {
"term": { // term 查询用于精确匹配 keyword, number, date 等非分析字段
"author": "Robert C. Martin"
}
}
}
你应该能搜到 ID 为 104 的图书。如果用match
查询author
字段,因为它是keyword
类型,match
查询对keyword
字段的行为是精确匹配,与term
类似。 -
搜索价格大于 60 的图书:
json
GET /books/_search
{
"query": {
"range": { // range 查询用于范围查找
"price": {
"gt": 60 // gt: greater than (大于)
}
}
}
}
你应该能搜到 ID 为 102, 103, 104 的图书。 -
组合查询:搜索包含 “Elasticsearch” 并且价格大于 50 的图书:
json
GET /books/_search
{
"query": {
"bool": { // bool 查询用于组合多个查询条件 (must, filter, should, must_not)
"must": [ // must 中的条件必须都满足
{
"multi_match": {
"query": "Elasticsearch",
"fields": ["title", "description"]
}
},
{
"range": {
"price": {
"gt": 50
}
}
}
]
}
}
}
你应该能搜到 ID 为 102 和 103 的图书。 -
按出版日期排序,并只返回特定字段:
json
GET /books/_search
{
"_source": ["title", "author", "publish_date"], // 只返回这三个字段
"query": {
"match_all": {}
},
"sort": [
{
"publish_date": { // 按 publish_date 字段排序
"order": "desc" // 降序排列 (最新在前)
}
}
]
}
结果会按出版日期从新到旧排列,并且每个文档只显示title
,author
,publish_date
字段。
-
通过这个简单的例子,你已经初步体验了如何使用 Elasticsearch 的 REST API 进行索引和搜索,并了解了 Query DSL 的基本用法。
7. 超越入门:接下来可以学什么?
恭喜你!你已经掌握了 Elasticsearch 的基本概念和核心操作。但这仅仅是冰山一角,Elasticsearch 的强大之处远不止于此。接下来,你可以继续深入学习以下方面:
- Kibana 的更多功能: Explore (探索) 数据、Visualize (可视化) 数据、Build Dashboards (构建仪表盘)、Management (管理集群、索引模式、用户等)。Kibana 是学习和使用 Elasticsearch 的得力助手。
- 更高级的 Query DSL: 学习更多查询类型(
term
,terms
,prefix
,wildcard
,regexp
,fuzzy
,phrase
,bool
查询的更多用法)、过滤上下文 vs 查询上下文的区别、相关性得分 (_score
) 的计算。 - 聚合 (Aggregations): 这是 Elasticsearch 强大的分析能力的体现。学习如何进行统计(求和、平均、最大最小)、分组 (
terms
aggregation)、范围统计 (range
aggregation) 等,以从数据中提取有价值的信息。 - 分布式特性: 深入理解分片和副本的工作原理、数据路由、集群的扩容和缩容、节点角色、高可用性。
- 索引生命周期管理 (ILM): 如何自动化管理随时间变化的索引,例如将旧数据迁移到更便宜的存储或定期删除。
- 快照与恢复 (Snapshot and Restore): 如何备份和恢复你的 Elasticsearch 数据。
- 性能优化: 如何设计高效的映射、优化查询语句、调整集群参数以提高性能。
- Elastic Stack 集成: 学习如何使用 Logstash 和 Beats 采集各种数据源的数据并导入 Elasticsearch。
- 安全性 (Security): 如果你在前面禁用了安全认证,现在是时候学习如何启用和配置用户、角色、权限,保护你的集群了。
- Elasticsearch 插件: 了解并安装常用的插件,如中文分词器、同义词插件等。
结论
从一个完全的新手到掌握 Elasticsearch 的核心概念和基本操作,你已经迈出了坚实的一步。Elasticsearch 是一个功能丰富、潜力巨大的工具,它在搜索和分析领域的应用越来越广泛。
学习是一个持续的过程。不断实践、探索官方文档、参与社区讨论是巩固和提升技能的最好方式。希望这篇超详细的入门教程为你提供了一个清晰的学习路径和坚实的基础。现在,去开启你的 Elasticsearch 探索之旅吧!祝你学习顺利!