Elasticsearch 入门与实战教程:从零开始构建强大的搜索与分析引擎
前言
在当今数据爆炸的时代,如何高效地存储、检索和分析海量数据成为了一个核心挑战。传统的关系型数据库在处理全文检索、实时分析和复杂的结构化/非结构化数据混合查询时往往显得力不从心。正是在这样的背景下,Elasticsearch 应运而生,并迅速成为全球领先的开源分布式搜索和分析引擎。
无论你是想为你的网站构建一个闪电般的搜索功能,还是需要对海量的日志数据进行实时监控和分析,亦或是构建一个强大的业务数据分析平台,Elasticsearch 都能提供强大的支持。
本文将带你从零开始,一步步走进 Elasticsearch 的世界。我们将详细讲解其核心概念、安装部署、基本数据操作、强大的搜索能力,并通过实战案例加深理解。
第一部分:初识 Elasticsearch
1.1 什么是 Elasticsearch?
Elasticsearch (简称 ES) 是一个基于 Apache Lucene™ 的开源分布式搜索和分析引擎。它以其分布式架构、高可用性、易扩展性和强大的实时搜索与分析能力而闻名。
主要特性:
- 分布式: 数据分散存储在多个节点上,天然支持水平扩展,可以处理 PB 级别的数据。
- 实时性: 数据写入后很快就可以被搜索到(近实时)。
- 全文检索: 基于 Lucene,提供强大的全文搜索功能,支持各种复杂的查询、过滤、排序和高亮。
- 分析功能: 内置强大的聚合(Aggregations)框架,可以对数据进行分组、计算统计指标,实现实时的数据分析和可视化。
- RESTful API: 提供简单易用的 RESTful 接口进行数据交互和集群管理。
- 高可用性: 通过复制(Replicas)机制保证数据冗余,节点故障时可以自动故障转移。
- 易扩展: 通过增加节点即可实现集群容量和吞吐量的扩展。
1.2 Elasticsearch 的应用场景
Elasticsearch 被广泛应用于各种领域:
- 站内搜索/电商搜索: 为网站、App、电商平台提供快速、精准、智能的搜索体验。
- 日志分析: 与 Logstash、Kibana 组成 ELK 技术栈(Elastic Stack),用于收集、处理、存储、搜索和可视化日志数据。
- 指标监控与分析: 存储和分析应用、服务器的性能指标,进行实时监控和报警。
- 安全信息和事件管理 (SIEM): 收集安全日志,进行威胁检测和安全分析。
- 地理位置搜索: 存储和搜索地理位置数据,进行附近的人/地点查询。
- 业务数据分析: 对业务数据进行多维度分析、报告生成。
1.3 Elasticsearch 与传统数据库的区别
虽然 Elasticsearch 可以存储数据,但它并非传统意义上的数据库。与关系型数据库(如 MySQL)或 NoSQL 数据库(如 MongoDB)相比,Elasticsearch 更专注于搜索和分析,尤其擅长处理非结构化或半结构化数据的全文检索和聚合计算。
- 数据结构: ES 使用 JSON 文档,比关系型数据库的表结构更灵活。
- 核心功能: ES 的核心是搜索和分析,数据库的核心是事务处理和结构化数据管理。
- 索引机制: ES 基于倒排索引(Inverted Index),非常适合全文检索;关系型数据库通常使用 B树索引。
- ACID 事务: ES 不完全支持 ACID 事务,适合写多读少的场景或对实时一致性要求不那么高的场景。
第二部分:核心概念详解
理解 Elasticsearch 的核心概念是掌握其使用的基础。
2.1 Cluster (集群)
一个 Elasticsearch 集群由一个或多个节点(Node)组成。集群是分布式的基础,它共享所有数据,并提供跨节点的索引和搜索能力。一个集群有一个唯一的名称来标识。
2.2 Node (节点)
一个节点是一个 Elasticsearch 服务的实例。节点是集群的一部分,负责存储数据、参与索引和搜索协调。节点在启动时会通过集群名称加入到对应的集群中。节点有不同的角色(如 master 节点、data 节点、ingest 节点等),但在入门阶段可以先简单理解为它是ES服务的一个运行实例。
2.3 Index (索引)
索引是 Elasticsearch 中存储数据的逻辑空间,类似于传统数据库中的“数据库”或“表”的概念,但其内部结构和机制完全不同。一个索引是相关文档的集合。例如,你可以创建一个索引来存储所有商品信息,另一个索引来存储所有用户订单。每个索引在创建时可以指定其分片和副本的数量。
2.4 Type (类型 – 注意:已废弃)
在 Elasticsearch 7.x 版本之前,一个索引可以包含多个类型(Type),类似于数据库中一个数据库包含多个表。然而,由于同一个索引内的不同类型可能会导致 Lucene 层面的一些问题,Type 概念在 7.x 版本中已被废弃,并在 8.x 版本中完全移除。现在,一个索引通常被设计为只存储一类结构相似的文档。
重要提示: 在使用 Elasticsearch 7.x 及以上版本时,无需考虑 Type,直接在 Index 下操作 Document 即可。通常,一个 Index 就代表一类数据。
2.5 Document (文档)
文档是 Elasticsearch 中存储的最小单元,类似于数据库中的“行”。每个文档是一个 JSON 对象,包含了一系列的键值对。文档是可索引的,意味着其内容可以被搜索。每个文档在索引内有一个唯一的 ID。
2.6 Shard (分片)
分片是将索引分解成更小的、可管理的部分。当一个索引非常大时,单台机器可能无法存储或处理。通过分片,可以将一个大索引的数据分布到集群中的多个节点上。每个分片本身就是一个功能完整的 Lucene 索引。分片可以是主分片(Primary Shard)或副本分片(Replica Shard)。索引在创建时会指定主分片的数量,主分片数量在创建后不能更改。
2.7 Replica (副本)
副本是主分片的拷贝。副本主要有两个作用:
1. 提高可用性: 当主分片所在的节点发生故障时,副本可以提升为新的主分片,保证数据不丢失和服务的连续性。
2. 提高读取性能: 搜索请求可以由主分片或其副本处理,增加搜索的并发能力。
索引在创建时可以指定每个主分片拥有的副本数量,副本数量可以在集群运行中动态调整。
分片与副本的关系示例:
假设创建一个索引,配置 number_of_shards: 3
和 number_of_replicas: 1
。
这意味着该索引将被分成 3 个主分片(P0, P1, P2)。
每个主分片会有一个副本(R0, R1, R2)。
整个索引在集群中会包含 3 个主分片和 3 个副本分片,总共 6 个分片实例。这些分片会被Elasticsearch自动分配到集群中的不同节点上,以实现负载均衡和高可用。
第三部分:安装与启动 Elasticsearch
我们将介绍本地安装 Elasticsearch 的基本方法。
3.1 安装 Java 环境
Elasticsearch 是基于 Java 开发的,因此需要安装 Java Runtime Environment (JRE) 或 Java Development Kit (JDK)。Elasticsearch 通常对 Java 版本有要求,请查阅对应 ES 版本的官方文档。推荐安装 OpenJDK 11 或更高版本。
可以通过以下命令检查 Java 版本:
bash
java -version
如果未安装或版本不符合要求,请先下载并安装。
3.2 下载 Elasticsearch
访问 Elasticsearch 官方下载页面:https://www.elastic.co/cn/downloads/elasticsearch
选择适合你操作系统的版本进行下载(.tar.gz
for Linux/macOS, .zip
for Windows)。这里我们以 Linux/macOS 为例。
“`bash
以 7.x 版本为例 (请根据实际需求选择版本)
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.5-linux-x86_64.tar.gz
或者下载最新的 8.x 版本
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.11.3-linux-x86_64.tar.gz
“`
3.3 解压与配置
解压下载的文件:
bash
tar -zxvf elasticsearch-7.17.5-linux-x86_64.tar.gz
cd elasticsearch-7.17.5
进入解压后的目录。重要的目录和文件:
* bin
: 启动脚本
* config
: 配置文件(elasticsearch.yml
, jvm.options
等)
* data
: 存储数据
* logs
: 存储日志
基本配置 (config/elasticsearch.yml
):
这是一个 YAML 格式的配置文件。对于单节点本地运行,通常只需要简单配置或保持默认即可。
“`yaml
集群名称,多个节点加入同一集群需要相同名称
cluster.name: my-application
节点名称
node.name: node-1
数据和日志目录 (默认在安装目录下,生产环境推荐配置到单独的盘)
path.data: /path/to/data
path.logs: /path/to/logs
绑定网络地址,默认只绑定本地回环地址 127.0.0.1
为了外部访问或多节点集群,需要绑定到网络接口地址
network.host: 192.168.1.10 # 特定 IP
network.host: 0.0.0.0 # 绑定所有接口 (仅限安全环境)
network.host: localhost # 仅绑定本地回环 (默认)
HTTP 端口,默认 9200
http.port: 9200
发现节点配置,用于多节点集群发现,单节点可忽略或使用默认
discovery.seed_hosts: [“host1”, “host2”]
对于 8.x 版本,安全配置是默认开启的。入门时可以禁用,但生产环境强烈建议开启。
在 elasticsearch.yml 中添加以下配置禁用安全认证 (不推荐用于生产环境)
xpack.security.enabled: false
xpack.security.transport.ssl.enabled: false
“`
对于单节点本地测试,通常默认配置即可,或者修改 network.host
为 0.0.0.0
或你的局域网 IP 如果需要从其他机器访问。请注意:在生产环境中禁用安全认证是非常危险的行为。
3.4 启动 Elasticsearch
在 Elasticsearch 根目录下,执行启动脚本:
bash
./bin/elasticsearch
如果一切正常,你会在控制台看到启动日志。等待日志输出类似 "message":"started"
的信息,表示节点已成功启动。
后台启动 (Linux/macOS):
bash
./bin/elasticsearch -d
日志输出到 logs
目录下。
3.5 验证安装
打开浏览器或使用 curl
命令,访问 Elasticsearch 的 HTTP 接口(默认端口 9200):
bash
curl http://localhost:9200
如果看到一个包含集群信息、节点信息、版本号等 JSON 响应,说明 Elasticsearch 已经成功运行。
json
{
"name" : "your-node-name",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "...",
"version" : {
"number" : "7.17.5", // 或 8.x 版本
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "...",
"build_date" : "...",
"build_snapshot" : false,
"lucene_version" : "8.11.1",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
安装 Kibana (可选但强烈推荐):
Kibana 是与 Elasticsearch 配套的可视化和管理工具。安装对应版本的 Kibana,修改其配置文件 (config/kibana.yml
) 中的 elasticsearch.hosts
指向你的 Elasticsearch 节点地址,然后启动 Kibana。通过浏览器访问 Kibana 的 Web 界面(默认端口 5601),可以在 Dev Tools 中方便地执行 Elasticsearch API 命令。
第四部分:基本数据操作 (CRUD)
Elasticsearch 提供 RESTful API 进行数据操作。我们将使用 curl
命令作为示例,你在 Kibana 的 Dev Tools 中也可以方便地执行这些命令。
4.1 创建/索引文档 (Index Document)
索引文档是将数据存储到 Elasticsearch 中的过程。你可以指定文档 ID,也可以让 ES 自动生成。
自动生成 ID: 使用 POST
请求到 /{index_name}/_doc/
路径。
“`bash
索引一个用户文档到 ‘users’ 索引
curl -X POST “localhost:9200/users/_doc/” -H “Content-Type: application/json” -d’
{
“username”: “zhangsan”,
“age”: 30,
“city”: “Beijing”,
“join_date”: “2023-01-15”
}
‘
``
_id
响应会包含索引名称、自动生成的文档 ID () 和版本号 (
_version`)。
指定文档 ID: 使用 PUT
请求到 /{index_name}/_doc/{document_id}
路径。如果该 ID 已存在,会替换原有文档;如果不存在,则创建新文档。
“`bash
索引一个 ID 为 ‘1’ 的商品文档到 ‘products’ 索引
curl -X PUT “localhost:9200/products/_doc/1” -H “Content-Type: application/json” -d’
{
“product_name”: “Laptop”,
“brand”: “Dell”,
“price”: 8500.00,
“in_stock”: true,
“tags”: [“electronics”, “computer”]
}
‘
“`
使用 _create
强制创建 (如果 ID 已存在则失败): 使用 PUT
请求到 /{index_name}/_create/{document_id}
路径。
“`bash
尝试创建一个 ID 为 ‘1’ 的商品文档,如果已存在则失败
curl -X PUT “localhost:9200/products/_create/1” -H “Content-Type: application/json” -d’
{
“product_name”: “Laptop”,
“brand”: “Dell”,
“price”: 8500.00,
“in_stock”: true,
“tags”: [“electronics”, “computer”]
}
‘
“`
4.2 获取文档 (Get Document)
使用 GET
请求到 /{index_name}/_doc/{document_id}
路径来获取指定 ID 的文档。
“`bash
获取 users 索引下 ID 为 ‘auto_generated_id’ 的文档 (替换为实际ID)
curl -X GET “localhost:9200/users/_doc/auto_generated_id”
获取 products 索引下 ID 为 ‘1’ 的文档
curl -X GET “localhost:9200/products/_doc/1”
``
_source
响应会包含文档的索引、ID、版本以及字段,
_source就是原始的 JSON 文档内容。
found: true` 表示文档存在。
4.3 更新文档 (Update Document)
更新文档有两种主要方式:全量替换和部分更新。
全量替换 (Full Replacement): 使用 PUT
请求到 /index_name/_doc/{document_id}
,并提供完整的文档内容。这会删除旧文档,然后索引新文档(版本号会增加)。
“`bash
全量更新 ID 为 ‘1’ 的商品文档
curl -X PUT “localhost:9200/products/_doc/1” -H “Content-Type: application/json” -d’
{
“product_name”: “Gaming Laptop”, # 名称改变
“brand”: “Dell”,
“price”: 9999.99, # 价格改变
“in_stock”: false, # 状态改变
“tags”: [“electronics”, “computer”, “gaming”] # 标签改变
}
‘
“`
部分更新 (Partial Update): 使用 POST
请求到 /{index_name}/_update/{document_id}
路径,并在请求体中使用 doc
字段指定要修改的字段,或者使用 script
字段执行脚本更新。部分更新不会替换整个文档,只会修改指定字段,效率更高。
使用 doc
字段:
“`bash
部分更新 ID 为 ‘1’ 的商品文档,只修改价格和库存状态
curl -X POST “localhost:9200/products/_update/1” -H “Content-Type: application/json” -d’
{
“doc”: {
“price”: 9500.00,
“in_stock”: true
}
}
‘
“`
使用 script
字段:适用于更复杂的更新逻辑,例如对字段进行计算或增减。
“`bash
使用脚本将 ID 为 ‘1’ 的商品价格降低 100
curl -X POST “localhost:9200/products/_update/1” -H “Content-Type: application/json” -d’
{
“script”: {
“source”: “ctx._source.price -= 100”,
“lang”: “painless” # Painless 是 Elasticsearch 推荐的脚本语言
}
}
‘
“`
4.4 删除文档 (Delete Document)
使用 DELETE
请求到 /{index_name}/_doc/{document_id}
路径。
“`bash
删除 products 索引下 ID 为 ‘1’ 的文档
curl -X DELETE “localhost:9200/products/_doc/1”
``
result: deleted`)。
响应会指示操作是否成功 (
4.5 批量操作 (Bulk API)
Elasticsearch 提供了 _bulk
API 来执行多个索引、创建、更新或删除操作,这比单独发送每个请求效率高得多。请求体格式比较特殊,是 newline-delimited JSON (NDJSON)。
每个操作由两行组成:一行是操作元数据(operation metadata),指定操作类型 (index
, create
, update
, delete
)、索引和文档 ID;另一行是文档本身(对于 index
和 create
)或更新信息(对于 update
)。delete
操作不需要文档内容。
bash
curl -X POST "localhost:9200/_bulk" -H "Content-Type: application/json" -d'
{"index": {"_index": "users", "_id": "2"}}
{"username": "lisi", "age": 25, "city": "Shanghai", "join_date": "2023-03-10"}
{"create": {"_index": "users", "_id": "3"}}
{"username": "wangwu", "age": 35, "city": "Guangzhou", "join_date": "2022-05-20"}
{"update": {"_index": "products", "_id": "1"}}
{"doc": {"price": 9000.00}}
{"delete": {"_index": "users", "_id": "auto_generated_id"}}
' # 注意:最后一行必须是换行符
_bulk
API 是导入大量数据时的首选方式。
第五部分:强大的搜索能力
搜索是 Elasticsearch 的核心功能。它提供了丰富灵活的查询语言——Query DSL (Domain Specific Language),基于 JSON 构建。
5.1 基本搜索 _search
使用 GET
或 POST
请求到 /{index_name}/_search
路径。GET
请求可以将查询参数放在 URL 中,POST
请求则将查询体放在请求体中。对于复杂的查询,通常使用 POST
。
“`bash
搜索 users 索引下的所有文档 (match_all query)
curl -X GET “localhost:9200/users/_search” -H “Content-Type: application/json” -d’
{
“query”: {
“match_all”: {}
}
}
‘
``
hits.total
响应包含匹配到的总数 ()、耗时 (
took) 以及匹配到的文档列表 (
hits.hits)。每个文档在列表中包含索引、ID、得分 (
_score) 和源文档 (
_source`)。
5.2 Query DSL 核心结构
Query DSL 通常包含在 query
字段中,其内部可以是各种类型的查询。
json
{
"query": {
"YOUR_QUERY_TYPE": {
// Query parameters
}
},
// Optional parameters like size, from, sort, _source filtering, etc.
"size": 10, // 返回结果数量,默认10
"from": 0, // 分页起始位置
"sort": [ // 排序
{ "field_name": "order" }
],
"_source": ["field1", "field2"] // 只返回指定字段
}
5.3 常用查询类型 (Query Types)
-
Match Query: 执行全文搜索,会对查询词进行分词处理。
“`json
搜索 products 索引中 product_name 字段包含 “Laptop” 的文档
{
“query”: {
“match”: {
“product_name”: “Laptop”
}
}
}
``
match` 查询会将 “Laptop” 分词后(例如,如果使用 standard analyzer,”Laptop” 就是一个词),去倒排索引中查找包含该词的文档。
默认情况下, -
Term Query: 精确匹配,不会对查询词进行分词。适用于关键字、数字、日期等精确值查找。通常用于非文本字段或
keyword
类型的字段。“`json
搜索 users 索引中 city 字段精确匹配 “Beijing” 的文档
{
“query”: {
“term”: {
“city.keyword”: “Beijing” # 注意:text字段需要使用 .keyword 后缀进行term查询
}
}
}
“` -
Range Query: 查找某一范围内的文档。适用于数字和日期字段。
“`json
搜索 products 索引中 price 在 8000 到 10000 之间的文档 (包含边界)
{
“query”: {
“range”: {
“price”: {
“gte”: 8000,
“lte”: 10000
}
}
}
}搜索 users 索引中 join_date 在 2023 年之后 (不包含) 的文档
{
“query”: {
“range”: {
“join_date”: {
“gt”: “2023-01-01”
}
}
}
}
``
gt
范围操作符:(大于),
gte(大于等于),
lt(小于),
lte` (小于等于)。 -
Bool Query: 组合多个查询条件,类似于 SQL 的 AND, OR, NOT。包含以下子句:
must
: 必须匹配,相当于 AND。会计算得分。filter
: 必须匹配,相当于 AND。不会计算得分,结果可缓存,适合用于过滤。should
: 应该匹配,相当于 OR。至少满足一个 should 子句,文档就会被返回(除非有 must 或 filter)。会计算得分。must_not
: 必须不匹配,相当于 NOT。不会计算得分。
filter
子句是提高搜索性能的关键,因为它们不会计算相关性得分 (_score
),并且结果易于缓存。“`json
搜索 products 索引中 product_name 包含 “Laptop”,并且 price 小于 10000,并且 in_stock 为 true 的文档
{
“query”: {
“bool”: {
“must”: [
{
“match”: {
“product_name”: “Laptop”
}
}
],
“filter”: [ # 使用 filter 进行精确过滤和范围过滤,不影响得分
{
“range”: {
“price”: {
“lt”: 10000
}
}
},
{
“term”: {
“in_stock”: true
}
}
]
}
}
}
“`
5.4 全文搜索与 Mapping、Analyzer
Elasticsearch 的全文搜索能力很大程度上依赖于 Mapping 和 Analyzer。
-
Mapping (映射): 定义了索引中文档及其字段的结构和数据类型。类似于数据库表结构定义。Elasticsearch 默认支持动态映射,即在你索引第一个文档时,它会尝试猜测字段类型并创建映射。但这并不总是最优的,特别对于文本字段。为了精确控制搜索行为,通常需要手动创建或修改映射。
text
: 适合全文检索的字段,会进行分词处理。keyword
: 适合精确值匹配的字段,不会分词。integer
,float
,long
,double
: 数字类型。boolean
: 布尔类型。date
: 日期类型。object
: JSON 对象。nested
: 特殊的对象类型,用于独立索引对象数组中的每个对象。
创建索引时指定 Mapping:
bash
curl -X PUT "localhost:9200/my_documents" -H "Content-Type: application/json" -d'
{
"mappings": {
"properties": {
"title": {
"type": "text",
"analyzer": "ik_smart" # 指定中文分词器 (需要安装插件)
},
"content": {
"type": "text"
},
"publish_date": {
"type": "date"
},
"tags": {
"type": "keyword"
}
}
}
}
' -
Analyzer (分析器): 用于处理文本字段,包括分词(Tokenization)、转换(如转小写、去除停用词)等。 Elasticsearch 有内置的分析器(如
standard
分析器),也支持安装插件(如ik-analyzer
用于中文分词)或自定义分析器。standard
分析器:基于 Unicode Text Segmentation 算法,适用于多种语言,但对中文支持不佳(单个汉字作为一个词)。- 中文分词器(如
ik-analyzer
):能正确将中文文本切分成有意义的词语。安装ik-analyzer
插件后,可以在 Mapping 中指定analyzer: "ik_smart"
或analyzer: "ik_max_word"
。
理解 Mapping 和 Analyzer 对于构建高效准确的搜索至关重要。不指定时,Elasticsearch 会尝试猜测并使用默认设置。
5.5 高亮 (Highlighting)
在搜索结果中高亮显示匹配的关键词,可以帮助用户快速定位相关信息。
“`json
搜索 products 索引中 product_name 包含 “Laptop”,并高亮显示匹配词
{
“query”: {
“match”: {
“product_name”: “Laptop”
}
},
“highlight”: {
“fields”: {
“product_name”: {}
}
}
}
``
hits.hits
响应中的数组会包含
highlight字段,其中是要高亮的字段及其带有 HTML 标签(默认是
`)的内容。
第六部分:常用的高级特性初步
6.1 Aggregations (聚合)
聚合是 Elasticsearch 强大的分析功能。它允许你对搜索结果进行分组、计算统计指标(如总和、平均值、最大值、最小值、计数等),实现数据分析和商业智能。类似于 SQL 中的 GROUP BY 和各种聚合函数(COUNT, SUM, AVG, MIN, MAX)。
聚合有不同的类型,如:
* Bucket Aggregations: 按某些标准(如字段值、范围、日期间隔)将文档分组到不同的“桶”中。常用的有 terms
(按字段值分组), range
(按范围分组), date_histogram
(按日期间隔分组)。
* Metric Aggregations: 对桶内的文档计算度量指标。常用的有 count
, sum
, avg
, min
, max
, stats
。
聚合通常与查询结合使用,先通过查询过滤出感兴趣的文档集合,然后对这个集合进行聚合分析。
“`json
搜索 products 索引,并按 brand 字段进行分组,计算每组的商品数量
{
“size”: 0, # 不返回搜索结果,只返回聚合结果
“aggs”: { # 定义聚合
“products_by_brand”: { # 聚合名称 (自定义)
“terms”: { # 聚合类型:terms aggregation (按字段值分组)
“field”: “brand.keyword”, # 聚合字段 (keyword 类型适合精确分组)
“size”: 10 # 返回前10个品牌
}
}
}
}
``
aggregations
响应会包含字段,其中是
products_by_brand` 聚合的结果,列出每个品牌及其文档数量。
你也可以嵌套聚合,例如先按品牌分组,再在每个品牌内按价格范围分组。
“`json
按 brand 分组,并在每个品牌内按 price 分组 (低于5000, 5000-10000, 高于10000)
{
“size”: 0,
“aggs”: {
“products_by_brand”: {
“terms”: {
“field”: “brand.keyword”
},
“aggs”: { # 嵌套聚合
“price_ranges”: {
“range”: {
“field”: “price”,
“ranges”: [
{ “to”: 5000 },
{ “from”: 5000, “to”: 10000 },
{ “from”: 10000 }
]
}
}
}
}
}
}
“`
聚合是 Elasticsearch 实现实时数据仪表盘和报表的基础,在 Kibana 中广泛使用。
6.2 索引管理
Elasticsearch 提供了丰富的 API 来管理索引,如创建、删除、查看设置和映射、打开/关闭索引等。
“`bash
查看所有索引
curl -X GET “localhost:9200/_cat/indices?v” # 使用 _cat API 获取简洁列表
查看特定索引的设置和映射
curl -X GET “localhost:9200/my_documents?pretty” # pretty 参数美化输出
“`
6.3 集群管理
通过 _cat
API 可以方便地查看集群状态、节点信息、分片分布等。
“`bash
查看集群健康状态 (green: 健康, yellow: 主分片正常但有副本未分配, red: 有主分片丢失)
curl -X GET “localhost:9200/_cat/health?v”
查看节点列表
curl -X GET “localhost:9200/_cat/nodes?v”
查看分片分布
curl -X GET “localhost:9200/_cat/shards?v”
“`
第七部分:实战案例:构建一个简单的文章搜索系统
假设我们要构建一个文章搜索系统,包含文章标题、内容、作者和发布日期。
步骤 1:设计 Mapping
我们需要一个索引来存储文章。标题和内容需要全文检索,作者需要精确匹配,发布日期需要按范围查询和排序。同时,为了支持中文搜索,我们将为标题和内容字段配置中文分词器(假设已安装并配置 ik-analyzer
插件)。
“`bash
创建 articles 索引并定义 Mapping
curl -X PUT “localhost:9200/articles” -H “Content-Type: application/json” -d’
{
“settings”: {
“number_of_shards”: 1, # 入门示例,单节点够用
“number_of_replicas”: 0 # 入门示例,不配置副本
},
“mappings”: {
“properties”: {
“title”: {
“type”: “text”,
“analyzer”: “ik_smart”
},
“content”: {
“type”: “text”,
“analyzer”: “ik_smart”
},
“author”: {
“type”: “keyword” # 作者名精确匹配
},
“publish_date”: {
“type”: “date”
}
}
}
}
‘
“`
步骤 2:索引示例文档
使用 _bulk
API 批量导入几篇示例文章。
bash
curl -X POST "localhost:9200/_bulk" -H "Content-Type: application/json" -d'
{"index": {"_index": "articles", "_id": "1"}}
{"title": "Elasticsearch 入门指南", "content": "这是一篇关于 Elasticsearch 基础概念和入门使用的文章。", "author": "张三", "publish_date": "2023-01-10"}
{"index": {"_index": "articles", "_id": "2"}}
{"title": "深入理解 Elasticsearch 查询 DSL", "content": "本文详细介绍了 Elasticsearch 的查询 DSL,包括各种查询类型和组合方式。", "author": "李四", "publish_date": "2023-03-15"}
{"index": {"_index": "articles", "_id": "3"}}
{"title": "Elasticsearch 聚合功能实战", "content": "通过实战案例,学习如何使用 Elasticsearch 的聚合功能进行数据分析。", "author": "张三", "publish_date": "2023-05-20"}
{"index": {"_index": "articles", "_id": "4"}}
{"index": {"_index": "articles", "_id": "5"}}
{"title": "使用 Kibana 进行日志分析", "content": "介绍如何利用 Kibana 配合 Elasticsearch 进行日志收集、可视化和分析。", "author": "王五", "publish_date": "2023-06-01"}
'
步骤 3:执行搜索
简单搜索: 搜索标题或内容中包含 “Elasticsearch” 的文章。
bash
curl -X GET "localhost:9200/articles/_search" -H "Content-Type: application/json" -d'
{
"query": {
"multi_match": { # multi_match 可以在多个字段中搜索
"query": "Elasticsearch",
"fields": ["title", "content"]
}
}
}
'
组合搜索: 搜索标题或内容包含 “Elasticsearch”,并且作者是 “张三” 的文章。
bash
curl -X GET "localhost:9200/articles/_search" -H "Content-Type: application/json" -d'
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "Elasticsearch",
"fields": ["title", "content"]
}
}
],
"filter": [ # 作者是精确匹配,使用 filter 性能更好
{
"term": {
"author.keyword": "张三"
}
}
]
}
}
}
'
带过滤和排序的搜索: 搜索标题或内容包含 “Elasticsearch”,发布日期在 2023 年 3 月 1 日之后的文章,并按发布日期降序排列。
bash
curl -X GET "localhost:9200/articles/_search" -H "Content-Type: application/json" -d'
{
"query": {
"bool": {
"must": [
{
"multi_match": {
"query": "Elasticsearch",
"fields": ["title", "content"]
}
}
],
"filter": [
{
"range": {
"publish_date": {
"gt": "2023-03-01"
}
}
}
]
}
},
"sort": [ # 按发布日期降序排序
{
"publish_date": "desc"
}
],
"highlight": { # 添加高亮
"fields": {
"title": {},
"content": {}
}
}
}
'
步骤 4:进行聚合分析
统计每位作者发布的文章数量。
bash
curl -X GET "localhost:9200/articles/_search" -H "Content-Type: application/json" -d'
{
"size": 0, # 只返回聚合结果
"aggs": {
"articles_by_author": { # 聚合名称
"terms": {
"field": "author.keyword" # 按作者进行分组
}
}
}
}
'
结果将显示每位作者(张三、李四、王五)及其对应的文章计数。
这个简单的实战案例展示了如何结合 Mapping、索引、查询和聚合来构建一个基本的搜索和分析系统。在实际应用中,你可能还需要考虑更复杂的查询逻辑、分词器的选择、性能优化、集群扩展等方面的问题。
第八部分:进阶学习与资源
- 官方文档: Elasticsearch 的官方文档非常详细和权威,是最好的学习资源。
- Elastic Stack: 深入了解与 Elasticsearch 集成的其他组件,如 Kibana (可视化), Logstash (数据采集处理), Beats (轻量级数据采集器)。
- 插件生态: 探索各种有用的插件,如各种分析器插件、安全插件等。
- 性能优化: 学习如何优化查询性能、索引性能,调整集群参数。
- 集群管理与运维: 学习如何监控集群、处理故障、进行扩容和升级。
- Elastic Cloud: 了解 Elastic 官方提供的云服务,可以省去自行运维的麻烦。
结论
Elasticsearch 是一个功能强大、灵活且易于扩展的分布式搜索和分析引擎。通过本文的学习,你应该对 Elasticsearch 的核心概念、安装使用、基本数据操作以及强大的搜索和分析能力有了初步的了解。从入门到精通 Elasticsearch 需要持续的学习和实践,但掌握了这些基础知识,你已经迈出了构建高效搜索和数据分析应用的第一步。
希望这篇详细的教程对你有所帮助!祝你在 Elasticsearch 的探索之路上一帆风顺!