文章目录
- [ElasticSearch之Kibana 入门指南](#ElasticSearch之Kibana 入门指南)
-
- 一、基础概念与环境准备
-
- [1. 核心组件对应关系](#1. 核心组件对应关系)
- [2. Ubuntu 环境部署(ES + Kibana)](#2. Ubuntu 环境部署(ES + Kibana))
-
- (1)依赖环境安装(Java)
- [(2)安装 ElasticSearch](#(2)安装 ElasticSearch)
- [(3)安装 Kibana(可视化工具)](#(3)安装 Kibana(可视化工具))
- 二、字段与映射(Mapping)
-
- [1. 常用字段类型](#1. 常用字段类型)
- [2. 字段核心配置参数](#2. 字段核心配置参数)
- [3. 映射操作语法](#3. 映射操作语法)
- 三、文档(Document)操作
-
- [1. 文档基本属性](#1. 文档基本属性)
- [2. 文档核心操作语法](#2. 文档核心操作语法)
- [3. 文档版本控制(并发控制)](#3. 文档版本控制(并发控制))
- 四、查询与聚合语法
-
- [1. 基础查询语法](#1. 基础查询语法)
- [2. 聚合操作语法](#2. 聚合操作语法)
- [五、Kibana 常用功能](#五、Kibana 常用功能)
- 六、注意事项
- [七、 案例](#七、 案例)
-
- [1. 创建索引](#1. 创建索引)
- [2. 插入文档数据](#2. 插入文档数据)
-
- [方法 1:指定文档 ID(推荐用于需要明确标识的场景)](#方法 1:指定文档 ID(推荐用于需要明确标识的场景))
- 示例:
- [方法 2:自动生成文档 ID(适合无需手动管理 ID 的场景)](#方法 2:自动生成文档 ID(适合无需手动管理 ID 的场景))
- 示例:
- 插入成功的响应
- 批量插入数据(高效方式)
- 注意事项
- [3. 根据条件查找数据](#3. 根据条件查找数据)
-
- [1. 查找所有数据(匹配所有文档)](#1. 查找所有数据(匹配所有文档))
- [2. 根据名字查找(精确匹配,`keyword` 类型)](#2. 根据名字查找(精确匹配,
keyword
类型)) - [3. 根据年龄查找(数值类型,支持范围查询)](#3. 根据年龄查找(数值类型,支持范围查询))
-
- (1)精确匹配某个年龄
- [(2)范围匹配(如年龄 > 20 且 <=30)](#(2)范围匹配(如年龄 > 20 且 <=30))
- [4. 复合查找(多条件组合查询)](#4. 复合查找(多条件组合查询))
-
- [示例:查找名字为 "王五" 且年龄 = 25 的文档](#示例:查找名字为 “王五” 且年龄 = 25 的文档)
- [示例:查找年龄 > 20 或 描述包含 "java" 的文档](#示例:查找年龄 > 20 或 描述包含 “java” 的文档)
- [5. 根据描述查找(全文检索,`text` 类型)](#5. 根据描述查找(全文检索,
text
类型)) - 总结
- [6. 查询结果解析](#6. 查询结果解析)
- [7. 删除数据](#7. 删除数据)
-
- [1. 删除单条文档(按文档 ID)](#1. 删除单条文档(按文档 ID))
- [2. 删除符合条件的多条文档(按查询条件)](#2. 删除符合条件的多条文档(按查询条件))
- [3. 删除整个索引(谨慎!)](#3. 删除整个索引(谨慎!))
- 总结
ElasticSearch之Kibana 入门指南
ps:因为某些版本问题,有部分可能不生效语法
一、基础概念与环境准备
1. 核心组件对应关系
ElasticSearch(ES)作为分布式搜索与分析引擎,其核心概念可与传统数据库类比,便于理解:
ElasticSearch 组件 | 传统数据库组件 | 说明 |
---|---|---|
索引(Index) | 数据库(Database) | 存储一类相似结构文档的集合,如 "用户索引""商品索引" |
文档(Document) | 行(Row) | 索引中的最小数据单元,以 JSON 格式存储 |
字段(Field) | 列(Column) | 文档的属性,如 "姓名""年龄",需指定类型(如 text、keyword) |
映射(Mapping) | 表结构(Schema) | 定义索引中字段的类型、分词器等配置,类似数据库表的结构定义 |
2. Ubuntu 环境部署(ES + Kibana)
(1)依赖环境安装(Java)
ES 依赖 Java 环境,推荐 OpenJDK 17:
bash
# 更新源并安装 OpenJDK 17
sudo apt update
sudo apt install openjdk-17-jdk -y
# 验证安装(输出版本信息即成功)
java -version
(2)安装 ElasticSearch
bash
# 1. 添加 ES 官方密钥
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
# 2. 添加 ES 仓库源(以 7.x 版本为例,其他版本替换版本号)
echo "deb [signed-by=/usr/share/keyrings/elasticsearch-keyring.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic.list > /dev/null
# 3. 安装并启动 ES
sudo apt update
sudo apt install elasticsearch -y
sudo systemctl enable --now elasticsearch # 开机自启
# 4. 验证 ES 运行(默认端口 9200)
curl http://localhost:9200 # 输出包含 "tagline": "You Know, for Search" 即成功
(3)安装 Kibana(可视化工具)
Kibana 需与 ES 版本完全一致,用于可视化操作 ES:
bash
# 1. 安装 Kibana(从已添加的 ES 仓库获取)
sudo apt install kibana -y
# 2. (可选)配置远程访问 ES(默认连接本地 9200)
sudo nano /etc/kibana/kibana.yml
# 取消注释并修改:elasticsearch.hosts: ["http://你的ES地址:9200"]
# 3. 启动 Kibana 并设置开机自启
sudo systemctl enable --now kibana
# 4. 验证(浏览器访问 http://localhost:5601,进入 Kibana 界面即成功)
二、字段与映射(Mapping)
1. 常用字段类型
字段类型决定数据的存储、查询和分析方式,需根据业务场景选择:
字段类型 | 核心特点 | 适用场景 | 映射配置示例 |
---|---|---|---|
text | 支持全文检索(会分词),默认不支持聚合 / 排序 | 长文本内容(文章正文、商品描述) | "content": { "type": "text", "analyzer": "ik_max_word" } (中文分词) |
keyword | 精确匹配(不分词),支持聚合 / 排序 | 短文本标识(标签、ID、状态) | "tag": { "type": "keyword" } |
numeric | 含 integer/long/float/double 等,支持范围查询 | 数值类数据(年龄、价格、数量) | "age": { "type": "integer" }, "price": { "type": "double" } |
date | 支持字符串 / 时间戳格式,可范围查询 | 时间类数据(创建时间、更新时间) | "create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" } |
boolean | 仅 true/false 两个值 | 状态标记(是否启用、是否删除) | "is_active": { "type": "boolean" } |
array | 无需声明类型,存储同类型值的集合 | 多值属性(用户标签列表、商品图片 URL 列表) | 文档中直接写入:"tags": ["tech", "es"] (映射按元素类型设为 keyword) |
object | 嵌套结构化数据 | 子对象属性(用户地址、商品规格) | "address": { "type": "object", "properties": { "city": { "type": "keyword" }, "street": { "type": "text" } } } |
nested | 解决普通 object 数组的 "跨对象匹配" 问题 | 嵌套列表(文章评论、订单商品列表) | "comments": { "type": "nested", "properties": { "user": { "type": "keyword" }, "content": { "type": "text" } } } |
2. 字段核心配置参数
在定义映射时,可通过参数自定义字段行为:
参数名 | 作用 | 示例 |
---|---|---|
analyzer |
索引时分词器(仅 text 类型) | "content": { "type": "text", "analyzer": "ik_max_word" } |
search_analyzer |
查询时分词器(默认与 analyzer 一致) | "content": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } |
format |
date 类型的可接受格式(多格式用逗号分隔) | "create_time": { "type": "date", "format": "yyyy-MM-dd,epoch_millis" } |
index |
是否创建索引(false 则不可查询) | "raw_data": { "type": "text", "index": false } |
fielddata |
text 类型启用聚合 / 排序(默认 false,耗内存) | "content": { "type": "text", "fielddata": true } |
fields |
为字段创建多类型(兼顾检索与聚合) | "name": { "type": "text", "fields": { "keyword": { "type": "keyword" } } } (name 检索,name.keyword 聚合) |
3. 映射操作语法
操作目的 | 请求方式 | 语法示例 | 说明 |
---|---|---|---|
创建索引时定义映射 | PUT | PUT /my_index { "mappings": { "properties": { "name": { "type": "text" }, "age": { "type": "integer" } } } } |
推荐:提前定义映射,避免自动推断错误 |
为已有索引添加新字段 | PUT | PUT /my_index/_mapping { "properties": { "email": { "type": "keyword" } } } |
支持添加新字段,不可修改已有字段类型 |
查看索引映射 | GET | GET /my_index/_mapping |
返回该索引的所有字段配置 |
重建索引(修改旧映射) | POST | POST _reindex { "source": { "index": "old_index" }, "dest": { "index": "new_index" } } |
旧索引数据迁移到新索引(新索引需提前定义正确映射) |
三、文档(Document)操作
文档是 ES 中最小的数据单元,所有数据交互围绕文档展开,以下为核心操作:
1. 文档基本属性
_index
:所属索引(如my_index
)_id
:唯一标识(可手动指定或 ES 自动生成 20 位随机字符)_source
:存储文档原始 JSON 数据(默认保留,可配置关闭)_version
:版本号(每次修改自增,用于并发控制)
2. 文档核心操作语法
操作类型 | 功能描述 | 请求方式 | 语法示例 | 说明 |
---|---|---|---|---|
创建文档 | 手动指定 ID | PUT | PUT /my_index/_doc/1 { "name": "张三", "age": 25, "is_active": true } |
ID 已存在则覆盖,版本号 + 1 |
自动生成 ID | POST | POST /my_index/_doc { "name": "李四", "age": 30 } |
无需指定 ID,ES 自动生成 | |
强制创建(避免覆盖) | PUT | PUT /my_index/_create/1 { "name": "王五" } |
ID 已存在则返回 409 错误 | |
查看文档 | 查看单个文档完整信息 | GET | GET /my_index/_doc/1 |
返回 _index /_id /_source 等信息 |
查看部分字段 | GET | GET /my_index/_doc/1?_source=name,age |
仅返回指定字段,减少数据传输 | |
判断文档是否存在 | HEAD | HEAD /my_index/_doc/1 |
存在返回 200,不存在返回 404(无响应体) | |
更新文档 | 全量更新(覆盖) | PUT | PUT /my_index/_doc/1 { "name": "张三", "age": 26 } |
未包含的字段会被删除 |
部分更新(推荐) | POST | POST /my_index/_update/1 { "doc": { "age": 27, "city": "北京" } } |
仅更新指定字段,新增字段自动添加 | |
脚本动态更新 | POST | POST /my_index/_update/1 { "script": { "source": "ctx._source.age += 1" } } |
通过 Painless 脚本修改(如年龄 + 1) | |
删除文档 | 删除单个文档 | DELETE | DELETE /my_index/_doc/1 |
版本号 + 1,物理删除延迟执行 |
批量删除(按条件) | POST | POST /my_index/_delete_by_query { "query": { "match": { "age": 25 } } } |
删除所有符合条件的文档,需谨慎 | |
批量操作 | 批量增 / 删 / 改 | POST | POST /_bulk { "index": { "_index": "my_index", "_id": "3" } } { "name": "赵六" } { "delete": { "_index": "my_index", "_id": "1" } } |
严格遵循 "元数据行 + 数据行" 结构,最后空一行;效率远高于单条操作 |
3. 文档版本控制(并发控制)
ES 通过 _seq_no
和 _primary_term
实现乐观锁(替代旧版本的 _version
),确保并发修改安全:
json
json
# 仅当文档 seq_no=3 且 primary_term=1 时更新(避免覆盖其他线程修改)
POST /my_index/_update/1?if_seq_no=3&if_primary_term=1
{ "doc": { "age": 28 } }
四、查询与聚合语法
ES 提供强大的查询与聚合能力,以下为常用操作:
1. 基础查询语法
查询类型 | 功能描述 | 请求方式 | 语法示例 | 说明 |
---|---|---|---|---|
匹配所有文档 | 查询索引中所有文档 | GET | GET /my_index/_search { "query": { "match_all": {} } } |
默认返回前 10 条,可通过分页调整 |
全文检索 | 按文本分词匹配 | GET | GET /my_index/_search { "query": { "match": { "name": "张" } } } |
对 text 类型字段生效,返回匹配结果 |
精确匹配 | 不分词,完全匹配值 | GET | GET /my_index/_search { "query": { "term": { "age": 25 } } } |
适用于 keyword/numeric 类型字段 |
多条件 "且" | 同时满足多个条件 | GET | GET /my_index/_search { "query": { "bool": { "must": [ { "match": { "name": "张" } }, { "term": { "age": 25 } } ] } } } |
must 内所有条件需同时满足 |
多条件 "或" | 满足任一条件 | GET | GET /my_index/_search { "query": { "bool": { "should": [ { "term": { "age": 25 } }, { "term": { "age": 30 } } ] } } } |
should 内任一条件满足即可 |
范围查询 | 数值 / 日期的区间匹配 | GET | GET /my_index/_search { "query": { "range": { "age": { "gte": 20, "lte": 30 } } } } |
gte (>=)、lte (<=)、gt (>)、lt (<) |
分页查询 | 控制返回结果的范围 | GET | GET /my_index/_search { "from": 0, "size": 10, "query": { "match_all": {} } } |
from (起始位置),size (每页条数) |
排序 | 按指定字段排序 | GET | GET /my_index/_search { "sort": [ { "age": { "order": "desc" } } ], "query": { "match_all": {} } } |
desc (降序)、asc (升序) |
指定返回字段 | 仅返回需要的字段 | GET | GET /my_index/_search { "_source": ["name", "age"], "query": { "match_all": {} } } |
减少数据传输,提升效率 |
2. 聚合操作语法
聚合用于对数据进行统计分析(如计数、平均值、分组),size:0
表示仅返回聚合结果,不返回原始文档:
聚合类型 | 功能描述 | 请求方式 | 语法示例 |
---|---|---|---|
统计总数 | 统计指定字段的非空值数量 | GET | GET /my_index/_search { "size": 0, "aggs": { "total_age": { "value_count": { "field": "age" } } } } |
平均值 | 计算数值字段的平均值 | GET | GET /my_index/_search { "size": 0, "aggs": { "avg_age": { "avg": { "field": "age" } } } } |
分组统计 | 按字段值分组并计数 | GET | GET /my_index/_search { "size": 0, "aggs": { "group_by_age": { "terms": { "field": "age" } } } } |
五、Kibana 常用功能
Kibana 是 ES 的可视化工具,核心功能如下:
-
Dev Tools(开发工具) :左侧菜单进入
Dev Tools
→Console
,可直接编写 ES 语法(替代 curl,支持自动补全),例如:json# 查询 my_index 中年龄为 25 的文档 GET /my_index/_search { "query": { "term": { "age": 25 } } }
-
Index Management(索引管理) :左侧菜单
Stack Management
→Index Management
,可视化查看所有索引的状态、映射、分片信息。 -
Discover(数据探索) :先在
Stack Management
→Index Patterns
创建索引模式(如my_index*
),再在Discover
中实时搜索、筛选文档。 -
Visualize Library(可视化报表):创建柱状图、折线图、饼图等,基于索引数据生成统计报表(如按年龄分组的用户数量分布)。
六、注意事项
- 版本兼容性:ES 与 Kibana 版本必须完全一致,否则无法通信。
- 字段类型不可修改 :字段创建后,类型和核心配置(如
analyzer
)无法修改,需通过重建索引解决。
七、 案例
1. 创建索引
bash
POST /my_index/_doc
{
"mappings":
{
"properties":
{
"name":
{
"type":"keyword"
},
"age":
{
"type":"integer"
},
"desc":
{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
这个 POST
请求的作用是在 Elasticsearch 中创建名为 my_index
的索引,并定义其字段映射(Mapping),即指定索引中各个字段的数据类型和解析规则。下面详细解释每个部分的作用:
- 整体操作:创建索引并定义映射
json
POST /my_index/_doc // 核心操作:创建名为 "my_index" 的索引
{
"mappings": { ... } // 定义该索引的字段映射规则
}
POST /my_index/_doc
:通过 HTTP 的POST
方法请求 Elasticsearch,创建一个名为my_index
的索引(如果该索引不存在)。mappings
:是定义索引结构的核心配置,用于指定字段的数据类型、分词方式等元数据(类似数据库表的「表结构定义」)。
- 字段映射详情 (
properties
内的配置)
properties
节点下定义了索引中包含的字段及其规则,这里包含 3 个字段:name
、age
、desc
。
(1)name: { "type": "keyword" }
type: "keyword"
:指定name字段为keyword类型。
- 特点 :
keyword
类型的字段会被当作「完整字符串」处理,不进行分词(例如"张三"
会被完整存储为一个词条)。 - 适用场景:适合精确匹配、排序、聚合(如按姓名精确查询、统计不同姓名的数量)。
(2)age: { "type": "integer" }
type: "integer"
:指定age字段为integer类型(32 位整数)。
- 特点 :存储数值型数据,支持数值运算(如范围查询
age > 18
)、排序等。 - 其他数值类型 :如果需要更大范围的数值,可使用
long
(64 位整数)、float
/double
(浮点数)等。
(3)desc: { "type": "text", "analyzer": "ik_max_word" }
type: "text"
:指定desc字段为text类型。
- 特点 :
text
类型用于存储长文本(如描述、正文),会进行分词处理(将文本拆分为多个词条,便于全文检索)。
analyzer: "ik_max_word"
:指定分词器为ik_max_word
(IK 分词器的「最细粒度拆分」模式)。
- 作用 :对中文文本进行精准分词(例如
"我爱编程"
会被拆分为["我", "爱", "编程"]
),确保中文搜索的准确性。 - 注意:需提前在 Elasticsearch 中安装 IK 分词器,否则会报错(可通过插件方式安装)。
2. 插入文档数据
在 Elasticsearch 中,向已创建的 my_index
索引插入数据(文档)主要有两种方式:指定文档 ID 或 自动生成 ID,具体操作如下:
方法 1:指定文档 ID(推荐用于需要明确标识的场景)
使用 PUT
请求,格式为:PUT /my_index/_doc/文档ID
示例:
json
# 插入 ID 为 1 的文档
PUT /my_index/_doc/1
{
"name": "张三",
"age": 25,
"desc": "热爱编程,擅长Java和Python"
}
# 插入 ID 为 2 的文档
PUT /my_index/_doc/2
{
"name": "李四",
"age": 30,
"desc": "数据分析师,熟悉Elasticsearch"
}
- 说明:
_doc
是 Elasticsearch 7.x+ 版本中默认的文档类型(7.x 后移除了多类型,统一使用_doc
)。文档ID
可以是数字、字符串等(如1
、user_123
),需唯一(重复 ID 会覆盖原有文档)。
方法 2:自动生成文档 ID(适合无需手动管理 ID 的场景)
使用 POST
请求,格式为:POST /my_index/_doc
示例:
json
# 自动生成 ID 插入文档
POST /my_index/_doc
{
"name": "王五",
"age": 28,
"desc": "前端开发工程师,精通Vue和React"
}
- 说明:
- 执行后,Elasticsearch 会自动生成一个唯一的 ID(如
_id: "QZJ32oUBRvjXrGfKdGjw"
),并返回在响应结果中。
- 执行后,Elasticsearch 会自动生成一个唯一的 ID(如
插入成功的响应
无论哪种方法,插入成功后会返回类似以下的响应:
json
{
"_index" : "my_index", // 所属索引
"_type" : "_doc", // 文档类型(固定为 _doc)
"_id" : "1", // 文档 ID(手动指定或自动生成)
"_version" : 1, // 文档版本(更新时会递增)
"result" : "created", // 操作结果(created 表示新建,updated 表示更新)
"took" : 2, // 耗时(毫秒)
"_shards" : { ... }, // 分片信息
"_seq_no" : 0,
"_primary_term" : 1
}
批量插入数据(高效方式)
如果需要插入多条数据,推荐使用 批量 API(_bulk
),减少请求次数:
json
POST /my_index/_bulk
{"index": {"_id": "3"}} // 第一条:指定 ID 为 3
{"name": "赵六", "age": 35, "desc": "后端架构师,擅长微服务"}
{"index": {}} // 第二条:自动生成 ID
{"name": "孙七", "age": 22, "desc": "实习生,学习Elasticsearch中"}
- 格式要求:
- 每行必须是 JSON 格式,且每行末尾需换行(包括最后一行)。
- 每条数据由两行组成:第一行是操作指令(
{"index": {"_id": "xxx"}}
),第二行是文档内容。
注意事项
- 插入的字段需与索引映射(
mappings
)中定义的类型匹配(如age
必须是整数,不能是字符串),否则会报错或自动转换类型。 - 若插入映射中未定义的字段,Elasticsearch 会自动推断类型并添加到映射中(建议提前定义好所有字段,避免自动推断不符合预期)。
3. 根据条件查找数据
在 Elasticsearch 中,你可以通过 _search
API 实现各种查询需求。以下是针对 my_index
索引的具体查询方法,包括查找所有数据、按名字 / 年龄 / 描述查询以及复合查询:
1. 查找所有数据(匹配所有文档)
使用 match_all
查询,返回索引中所有文档:
json
GET /my_index/_search
{
"query": {
"match_all": {} // 匹配所有文档
}
}
- 结果会包含所有文档,默认返回前 10 条,可通过
size
参数调整(如{"size": 100}
返回 100 条)。
2. 根据名字查找(精确匹配,keyword
类型)
name
字段是 keyword
类型(不分词,适合精确匹配),推荐用 term
查询:
json
GET /my_index/_search
{
"query": {
"term": {
"name": { // 字段名
"value": "王五" // 要匹配的名字(精确匹配)
}
}
}
}
- 注意:
term
查询对keyword
类型区分大小写(如匹配 "王五" 不会返回 "王五")。
3. 根据年龄查找(数值类型,支持范围查询)
age
是 integer
类型,可通过 term
(精确匹配)或 range
(范围匹配)查询:
(1)精确匹配某个年龄
json
GET /my_index/_search
{
"query": {
"term": {
"age": {
"value": 25 // 精确匹配年龄=25
}
}
}
}
(2)范围匹配(如年龄 > 20 且 <=30)
json
GET /my_index/_search
{
"query": {
"range": {
"age": {
"gt": 20, // 大于 20(gt = greater than)
"lte": 30 // 小于等于 30(lte = less than or equal)
}
}
}
}
- 其他范围参数:
gte
(大于等于)、lt
(小于)。
4. 复合查找(多条件组合查询)
使用 bool
查询组合多个条件(如 "名字是王五 且 年龄 > 20"),支持 must
(必须满足)、should
(或)、must_not
(必须不满足):
示例:查找名字为 "王五" 且年龄 = 25 的文档
json
GET /my_index/_search
{
"query": {
"bool": {
"must": [ // 所有条件必须满足
{ "term": { "name": "王五" } },
{ "term": { "age": 25 } }
]
}
}
}
示例:查找年龄 > 20 或 描述包含 "java" 的文档
json
GET /my_index/_search
{
"query": {
"bool": {
"should": [ // 满足任一条件即可
{ "range": { "age": { "gt": 20 } } },
{ "match": { "desc": "java" } }
]
}
}
}
5. 根据描述查找(全文检索,text
类型)
desc
是 text
类型(使用 IK 分词器),适合用 match
查询(会对查询词分词后匹配):
json
GET /my_index/_search
{
"query": {
"match": {
"desc": "java 开发" // 分词为 ["java", "开发"],匹配包含任一词语的文档
}
}
}
-
特点:会对查询词(如 "java 开发")进行分词,返回包含任一分词结果的文档(如 "擅长 java""开发工程师" 都会被匹配)。
-
若需要 "同时包含所有词语",用match_phrase:
json{ "query": { "match_phrase": { "desc": "java 开发" // 必须同时包含"java"和"开发",且顺序接近 } } }
总结
查询场景 | 推荐查询类型 | 核心特点 |
---|---|---|
所有数据 | match_all |
返回全部文档 |
名字精确匹配 | term |
针对 keyword 类型 |
年龄精确 / 范围匹配 | term / range |
针对数值类型 |
多条件组合 | bool (must 等) |
组合多个查询条件 |
描述全文检索 | match |
分词后匹配,适合模糊查询 |
描述精确短语匹配 | match_phrase |
匹配连续的短语,顺序相关 |
6. 查询结果解析
查询:
json
GET /my_index/_search
{
"query":
{
"term":
{
"name":
{
"value":"王五"
}
}
}
}
结果:
json
{
"took": 7,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1.2039728,
"hits": [
{
"_index": "my_index",
"_id": "3",
"_score": 1.2039728,
"_source": {
"name": "王五",
"age": 25,
"desc": "擅长c++开发"
}
}
]
}
}
解析:
这个 JSON 是 Elasticsearch _search
查询的标准响应结果,每个字段都对应查询的关键信息,下面逐层级解析每个字段的含义:
一、顶层核心字段(整体查询概况)
字段名 | 类型 | 含义 |
---|---|---|
took |
整数 | 查询耗时,单位为毫秒(示例中为 7ms),反映查询效率。 |
timed_out |
布尔值 | 查询是否超时(false 表示未超时,true 表示超时未完成)。 |
_shards |
对象 | 索引分片的查询情况(Elasticsearch 索引默认分为多个分片,分布式存储)。 |
hits |
对象 | 查询的核心结果集,包含匹配的文档数量、得分、具体文档内容。 |
二、_shards
字段(分片查询详情)
Elasticsearch 通过分片实现分布式查询,_shards
展示各分片的执行状态:
json
"_shards": {
"total": 1, // 参与查询的分片总数(示例中索引只有 1 个主分片)
"successful": 1, // 查询成功的分片数(1 个分片成功返回结果)
"skipped": 0, // 跳过查询的分片数(0 表示所有分片都参与了查询)
"failed": 0 // 查询失败的分片数(0 表示无分片失败,结果可靠)
}
- 若
failed > 0
,需检查分片状态(如节点离线、权限问题)。
三、hits
字段(查询结果核心)
hits
是查询结果的核心,包含「匹配文档统计」和「具体文档列表」:
hits.total
(匹配文档统计)
json
"total": {
"value": 1, // 匹配的文档总数(示例中只有 1 条文档符合条件)
"relation": "eq" // 总数的准确性(`eq` = equal,表示总数精确;`gte` = greater than or equal,表示总数是"至少"的估算值)
}
- Elasticsearch 7.0+ 中,当匹配文档数超过
track_total_hits
配置(默认 10000)时,relation
会变为gte
,value
显示估算值(避免全量统计影响性能)。
hits.max_score
(最高匹配得分)
- 数值类型(示例中为
1.2039728
),表示所有匹配文档中最高的相关性得分。 - 得分越高,说明文档与查询条件的相关性越强(如全文检索时,关键词出现次数越多、位置越靠前,得分越高)。
hits.hits
(具体匹配文档列表)
数组类型,每个元素是一条匹配的文档,包含文档的元数据和原始内容:
json
{
"_index": "my_index", // 文档所属的索引名(示例中为之前创建的 my_index)
"_id": "3", // 文档的唯一 ID(示例中是插入时手动指定的 ID=3)
"_score": 1.2039728, // 该文档的相关性得分(与 max_score 一致,因只有 1 条匹配)
"_source": { // 文档的**原始数据**(插入时提交的字段和值)
"name": "王五",
"age": 25,
"desc": "擅长c++开发"
}
}
_source
:存储文档的原始内容,查询时默认返回;若只需部分字段,可通过_source: ["name", "age"]
指定返回字段(减少数据传输)。_score
:仅在「相关性查询」(如match
、match_phrase
)中存在;「精确查询」(如term
、range
)若未指定排序,得分默认是 1.0。
总结
这个响应结果的核心信息是:本次查询耗时 7ms,未超时,1 个分片成功执行,共匹配到 1 条文档(ID=3,姓名 "王五"),该文档与查询条件的相关性得分为 1.2039728。
7. 删除数据
在 Elasticsearch 中删除数据主要有两种方式:删除单条文档 和删除整个索引(谨慎操作!)。根据需求选择对应的方式,具体操作如下:
1. 删除单条文档(按文档 ID)
如果已知要删除的文档 ID,使用 DELETE
请求删除指定文档:
语法:
json
DELETE /索引名/_doc/文档ID
示例(删除 my_index
中 ID 为 3 的文档):
json
DELETE /my_index/_doc/3
成功响应:
json
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "3",
"_version" : 2, // 版本号递增(原版本为 1,删除后变为 2)
"result" : "deleted", // 表示删除成功
"took" : 4,
"_shards" : { ... },
"_seq_no" : 1,
"_primary_term" : 1
}
注意:
- 如果文档 ID 不存在,会返回
result: "not_found"
,但不会报错。 - 删除后文档不会立即从磁盘中移除,而是标记为删除状态,后续会由 Elasticsearch 后台清理。
2. 删除符合条件的多条文档(按查询条件)
如果需要删除满足特定条件的所有文档(如删除年龄大于 30 的所有文档),使用 _delete_by_query
API:
语法:
json
POST /索引名/_delete_by_query
{
"query": { // 这里填写删除的条件(与查询数据的语法一致)
...
}
}
示例(删除 name
为 "张三" 的所有文档):
json
POST /my_index/_delete_by_query
{
"query": {
"term": {
"name": {
"value": "张三"
}
}
}
}
成功响应:
json
{
"took" : 12,
"timed_out" : false,
"total" : 1, // 匹配到的文档总数
"deleted" : 1, // 实际删除的文档数
"batches" : 1,
"version_conflicts" : 0,
"noops" : 0,
"retries" : { ... },
"throttled_millis" : 0,
"requests_per_second" : -1.0,
"throttled_until_millis" : 0,
"failures" : [ ]
}
注意:
- 条件必须精确,避免误删(建议先执行
_search
验证条件是否正确)。 - 大索引批量删除可能影响性能,可通过参数控制速度(如
?requests_per_second=50
限制每秒请求数)。
3. 删除整个索引(谨慎!)
如果需要删除索引中所有数据(包括索引结构),可以直接删除整个索引(此操作不可恢复):
语法:
json
DELETE /索引名
示例(删除 my_index
索引):
json
DELETE /my_index
成功响应:
json
{
"acknowledged" : true
}
警告:
- 删除索引会彻底清除该索引的所有数据和映射配置,无法恢复。
- 生产环境中建议限制
DELETE
索引的权限,避免误操作。
总结
需求场景 | 操作方式 | 关键点 |
---|---|---|
删除单条已知 ID 的文档 | DELETE /索引/_doc/ID |
精准删除,影响范围小 |
删除符合条件的多条文档 | POST /索引/_delete_by_query |
先查询验证条件,再执行删除,避免误删 |
删除整个索引(含结构) | DELETE /索引 |
谨慎操作!不可恢复,适用于彻底清理整个索引的场景 |