1. Elasticsearch基础操作全指南
Elasticsearch作为当前最流行的分布式搜索和分析引擎,几乎成了大数据领域的标配工具。但很多新手在初次接触时,往往被其看似复杂的REST API和查询语法吓退。实际上,只要掌握几个核心操作,就能应付80%的日常需求。我在使用ES的五年间,从单节点部署到管理上百节点的生产集群,总结出一套最实用的基础操作手册。
提示:本文所有示例均基于Elasticsearch 7.x版本,与6.x的主要语法差异会特别标注
1.1 环境准备与基本概念
安装Elasticsearch最简单的方式是使用Homebrew(Mac)或直接下载压缩包。以Mac为例:
brew tap elastic/tap brew install elastic/tap/elasticsearch-full elasticsearch启动后访问http://localhost:9200 能看到版本信息即表示成功。ES的核心概念需要提前了解:
- 索引(Index):相当于传统数据库的"库",是文档的集合
- 类型(Type):7.x后已废弃,现在一个索引只能包含一种类型
_doc - 文档(Document):JSON格式的基本数据单元
- 分片(Shard):索引的横向分割单元,分为主分片和副本分片
1.2 REST API基础格式
ES的所有操作都通过HTTP REST API完成,基本格式如下:
<HTTP方法> /<索引>/<类型>/<文档ID> { JSON请求体 }常用HTTP方法对应CRUD操作:
- GET:查询
- POST:创建/更新
- PUT:创建/修改
- DELETE:删除
2. 文档CRUD操作实战
2.1 创建文档
创建文档有两种方式,指定ID和不指定ID:
# 指定ID创建(PUT) PUT /products/_doc/1 { "name": "iPhone 13", "price": 5999, "tags": ["手机", "苹果"] } # 自动生成ID(POST) POST /products/_doc/ { "name": "MacBook Pro", "price": 12999 }注意:实际发送请求需要使用curl或Kibana Dev Tools。例如:
curl -XPUT "http://localhost:9200/products/_doc/1" -H 'Content-Type: application/json' -d' { "name": "iPhone 13" }'
2.2 查询文档
基础查询有三种常用形式:
# 1. 按ID查询 GET /products/_doc/1 # 2. 查询所有文档 GET /products/_search { "query": { "match_all": {} } } # 3. 条件查询 GET /products/_search { "query": { "match": { "name": "iPhone" } } }2.3 更新文档
ES的更新实际上是重建索引,有两种方式:
# 1. 全量替换 PUT /products/_doc/1 { "name": "iPhone 13 Pro", "price": 7999 } # 2. 局部更新 POST /products/_update/1 { "doc": { "price": 6999 } }2.4 删除文档
# 删除指定文档 DELETE /products/_doc/1 # 删除整个索引(谨慎操作!) DELETE /products3. 高级查询语法
3.1 复合查询
实际业务中经常需要组合多个条件:
GET /products/_search { "query": { "bool": { "must": [ { "match": { "name": "iPhone" } } ], "filter": [ { "range": { "price": { "gte": 5000 } } } ] } } }bool查询支持四种子句:
- must:必须满足,参与算分
- should:应该满足,满足会增加分数
- must_not:必须不满足
- filter:必须满足,但不参与算分
3.2 分页与排序
GET /products/_search { "from": 0, "size": 10, "sort": [ { "price": { "order": "desc" } } ] }重要提示:深度分页(如from=10000)会显著影响性能,推荐使用search_after参数
3.3 聚合分析
聚合是ES最强大的功能之一:
GET /products/_search { "aggs": { "price_stats": { "stats": { "field": "price" } }, "tags_count": { "terms": { "field": "tags.keyword" } } } }常用聚合类型:
- 指标聚合:avg, sum, max, min, stats
- 桶聚合:terms, date_histogram, range
4. 索引管理技巧
4.1 创建带映射的索引
PUT /products { "mappings": { "properties": { "name": { "type": "text" }, "price": { "type": "double" }, "tags": { "type": "keyword" } } } }字段类型选择建议:
- text:需要分词的字符串
- keyword:不需要分词的字符串(如标签、状态)
- date/double/long:对应类型数据
4.2 索引别名
别名是生产环境的最佳实践:
# 创建别名 POST /_aliases { "actions": [ { "add": { "index": "products_v1", "alias": "products" } } ] }使用别名可以实现:
- 无缝索引切换
- 基于时间的索引轮转
- 读写分离
5. 常见问题排查
5.1 集群健康问题
GET /_cluster/health状态解读:
- green:所有分片正常
- yellow:主分片正常,副本分片未分配
- red:有主分片不可用
5.2 查询性能优化
慢查询日志配置:
PUT /_settings { "index.search.slowlog.threshold.query.warn": "10s", "index.search.slowlog.threshold.fetch.debug": "500ms" }性能优化方向:
- 合理设置分片数(建议每个分片20-50GB)
- 使用filter代替query进行条件过滤
- 避免通配符查询
5.3 中文分词问题
安装IK分词器:
./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.16.2/elasticsearch-analysis-ik-7.16.2.zip测试分词效果:
POST /_analyze { "analyzer": "ik_max_word", "text": "中华人民共和国" }6. 实战经验分享
在管理大型ES集群时,有几个容易踩的坑值得特别注意:
映射爆炸问题:避免使用动态映射,特别是字段数量不可控的场景。我曾遇到一个日志索引因为自动创建了上万个字段导致集群崩溃的情况。解决方案是在模板中设置
"dynamic": "strict"。分片设置黄金法则:
- 单个分片大小控制在20-50GB
- 每个节点的分片数不超过每GB堆内存20个
- 对于时序数据,使用基于时间的索引(如logs-2023-01-01)
写入优化技巧:
- 批量写入使用_bulk API
- 适当增加
refresh_interval(默认1s) - 关闭副本分片进行大规模导入,完成后再开启
查询优化心得:
- 善用
_source过滤减少网络传输 - 对范围查询使用
date_nanos而非字符串 - 聚合查询时设置
size: 0避免返回命中文档
- 善用
一个实用的监控脚本:
#!/bin/bash ES_HOST="localhost:9200" # 集群状态 curl -s "$ES_HOST/_cluster/health?pretty" # 索引状态 curl -s "$ES_HOST/_cat/indices?v" # 节点状态 curl -s "$ES_HOST/_cat/nodes?v" # 热点线程 curl -s "$ES_HOST/_nodes/hot_threads"