忘机山人
本章导读:本章将详细介绍 Elasticsearch 的核心概念,包括索引、文档、映射、分片、副本、集群和节点等,这些概念是理解和使用 Elasticsearch 的基础。
索引是 Elasticsearch 中存储数据的逻辑命名空间,类似于关系型数据库中的"数据库"概念。一个索引包含一组具有相似特征的文档。
索引名称必须遵循以下规则:
\、/、*、?、"、<、>、|、空格、逗号、#:,但已废弃-、_、+ 开头. 或 ..// 创建索引
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
// 查看索引信息
GET /products
// 查看所有索引
GET /_cat/indices?v
// 删除索引
DELETE /products
索引有两类设置:
静态设置(创建后不可修改):
number_of_shards:主分片数量动态设置(可随时修改):
number_of_replicas:副本数量refresh_interval:刷新间隔max_result_window:最大返回结果数// 修改动态设置
PUT /products/_settings
{
"index": {
"number_of_replicas": 2,
"refresh_interval": "30s"
}
}
文档是 Elasticsearch 中的基本数据单元,以 JSON 格式存储。每个文档都属于一个索引,并有一个唯一的 ID。
一个文档包含以下元数据:
| 元数据 | 说明 |
|---|---|
_index | 文档所属的索引 |
_id | 文档的唯一标识符 |
_source | 文档的原始 JSON 内容 |
_version | 文档版本号 |
_seq_no | 序列号,用于并发控制 |
_primary_term | 主分片任期号 |
// 创建文档(指定 ID)
PUT /products/_doc/1
{
"name": "iPhone 15",
"price": 7999,
"category": "手机",
"brand": "Apple",
"created_at": "2024-01-01"
}
// 创建文档(自动生成 ID)
POST /products/_doc
{
"name": "MacBook Pro",
"price": 14999,
"category": "笔记本",
"brand": "Apple"
}
// 获取文档
GET /products/_doc/1
// 更新文档
POST /products/_update/1
{
"doc": {
"price": 7499
}
}
// 删除文档
DELETE /products/_doc/1
// 自动生成 ID
POST /products/_doc
{
"name": "Product A"
}
// 返回: "_id": "abc123xyz..."
// 手动指定 ID
PUT /products/_doc/my-product-001
{
"name": "Product B"
}
// 返回: "_id": "my-product-001"
映射定义了文档及其字段如何存储和索引。类似于关系型数据库中的表结构定义(Schema)。
Elasticsearch 支持多种字段类型:
核心类型:
| 类型 | 说明 | 示例 |
|---|---|---|
text | 全文搜索文本 | 商品描述、文章内容 |
keyword | 精确值 | 状态、标签、ID |
long | 长整型 | 大数值 |
integer | 整型 | 数量、年龄 |
double | 双精度浮点 | 价格、评分 |
boolean | 布尔值 | 是否上架 |
date | 日期 | 创建时间 |
object | JSON 对象 | 嵌套属性 |
nested | 嵌套对象数组 | 评论列表 |
特殊类型:
| 类型 | 说明 |
|---|---|
geo_point | 地理坐标点 |
geo_shape | 地理形状 |
ip | IP 地址 |
completion | 自动补全 |
dense_vector | 稠密向量 |
// 创建索引时定义映射
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"price": {
"type": "double"
},
"category": {
"type": "keyword"
},
"description": {
"type": "text"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"is_available": {
"type": "boolean"
},
"tags": {
"type": "keyword"
},
"location": {
"type": "geo_point"
}
}
}
}
// 查看映射
GET /products/_mapping
当索引一个包含新字段的文档时,Elasticsearch 会自动推断字段类型:
| JSON 类型 | 推断的 ES 类型 |
|---|---|
true / false | boolean |
| 整数 | long |
| 浮点数 | double |
| 日期格式字符串 | date |
| 其他字符串 | text + keyword |
| 对象 | object |
| 数组 | 取决于第一个元素 |
// 控制动态映射行为
PUT /products
{
"mappings": {
"dynamic": "strict", // true(默认)/false/strict
"properties": {
"name": { "type": "text" }
}
}
}
true:自动添加新字段(默认)false:忽略新字段,不索引但保存在 _sourcestrict:遇到新字段抛出异常分片是索引的水平分割单元。每个分片本质上是一个独立的 Lucene 索引,可以独立执行索引和搜索操作。
┌─────────────────────────────────────────────────────────┐
│ 索引 (Index) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Primary 0 │ │ Primary 1 │ │ Primary 2 │ │
│ │ (主分片) │ │ (主分片) │ │ (主分片) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Replica 0 │ │ Replica 1 │ │ Replica 2 │ │
│ │ (副本分片) │ │ (副本分片) │ │ (副本分片) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
// 创建索引时指定分片数
PUT /products
{
"settings": {
"number_of_shards": 3, // 主分片数(创建后不可修改)
"number_of_replicas": 1 // 每个主分片的副本数(可动态修改)
}
}
经验法则:
过度分片的问题:
// 查看分片分布
GET /_cat/shards/products?v
副本是主分片的完整复制。每个主分片可以有零个或多个副本。
// 修改副本数量
PUT /products/_settings
{
"index": {
"number_of_replicas": 2
}
}
节点数 = 1,副本数 = 1
┌─────────────────┐
│ Node 1 │
│ ┌───────────┐ │
│ │ Primary 0 │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ Replica 0 │ │ ← 无法分配!
│ │ UNASSIGNED│ │
│ └───────────┘ │
└─────────────────┘
节点数 = 2,副本数 = 1
┌─────────────────┐ ┌─────────────────┐
│ Node 1 │ │ Node 2 │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ Primary 0 │ │ │ │ Replica 0 │ │ ← 正常分配
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
集群是一组协同工作的 Elasticsearch 节点。集群通过唯一的名称标识,默认名称为 elasticsearch。
集群有三种健康状态:
| 状态 | 颜色 | 说明 |
|---|---|---|
| Green | 🟢 | 所有主分片和副本分片都已分配 |
| Yellow | 🟡 | 所有主分片已分配,但部分副本未分配 |
| Red | 🔴 | 部分主分片未分配,数据不完整 |
// 查看集群健康状态
GET /_cluster/health
// 返回示例
{
"cluster_name": "my-cluster",
"status": "green",
"number_of_nodes": 3,
"number_of_data_nodes": 3,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
# elasticsearch.yml
cluster.name: my-cluster
node.name: node-1
network.host: 0.0.0.0
discovery.seed_hosts: ["node1:9300", "node2:9300", "node3:9300"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
节点是集群中的单个 Elasticsearch 实例。每个节点都有唯一的名称和角色。
| 角色 | 配置 | 说明 |
|---|---|---|
| Master | node.roles: [master] | 管理集群状态、索引创建删除、分片分配 |
| Data | node.roles: [data] | 存储数据、执行 CRUD、搜索、聚合 |
| Ingest | node.roles: [ingest] | 执行 Ingest Pipeline 预处理 |
| Coordinating | node.roles: [] | 路由请求、合并结果(无特定角色) |
| ML | node.roles: [ml] | 执行机器学习任务 |
| Remote Cluster Client | node.roles: [remote_cluster_client] | 跨集群搜索 |
# 专用主节点
node.roles: [master]
# 专用数据节点
node.roles: [data]
# 数据 + Ingest 节点
node.roles: [data, ingest]
# 协调节点(无角色)
node.roles: []
# 默认(所有角色)
node.roles: [master, data, data_content, data_hot, data_warm, data_cold, ingest, ml, remote_cluster_client, transform]
// 查看所有节点
GET /_cat/nodes?v
// 查看节点详细信息
GET /_nodes
// 查看特定节点统计
GET /_nodes/stats
┌─────────────────────────────────────────────────────────────────────┐
│ Cluster (集群) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Node 1 (节点) │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Index (索引) │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Shard P0 │ │ Shard R1 │ │ │ │
│ │ │ │ ┌─────────┐ │ │ │ │ │ │
│ │ │ │ │Document │ │ │ │ │ │ │
│ │ │ │ │ _id: 1 │ │ │ │ │ │ │
│ │ │ │ │ _source │ │ │ │ │ │ │
│ │ │ │ └─────────┘ │ │ │ │ │ │
│ │ │ │ ┌─────────┐ │ │ │ │ │ │
│ │ │ │ │Document │ │ │ │ │ │ │
│ │ │ │ │ _id: 2 │ │ │ │ │ │ │
│ │ │ │ └─────────┘ │ │ │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ Mapping (映射): 定义字段类型和索引方式 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Node 2 (节点) │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Shard P1 │ │ Shard R0 │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
| Elasticsearch | 关系型数据库 | 说明 |
|---|---|---|
| Index | Database | 数据的逻辑容器 |
| Mapping | Schema | 数据结构定义 |
| Document | Row | 数据的基本单元 |
| Field | Column | 数据的属性 |
| Shard | Partition | 数据的物理分割 |
⚠️ 注意:这个对比仅用于帮助理解,ES 和关系型数据库的设计理念有本质区别。
本章介绍了 Elasticsearch 的核心概念:
理解这些概念是使用 Elasticsearch 的基础,后续章节将在此基础上深入讲解各个功能。

评论
0暂无评论