Elasticsearch
约 2247 字大约 7 分钟
2025-08-26
Elasticsearch 6.2.4 常用操作笔记
本笔记主要基于 Elasticsearch 6.2.4 版本整理,6.2.4 与 7.x/8.x 在 API 上存在一些区别如下:
- 索引(
index)/ 类型(type):6.2.4仍然使用type(通常为_doc或自定义),7.x起逐步废弃type - 乐观锁字段:
6.2.4主要使用_version做并发控制,_seq_no与_primary_term在6.3.0之后引入,6.2.4默认响应中不包含 - 路由(
_routing):支持,语义与7/8基本一致。 - 模板(
index template):语法与7/8相近,但6.x里通常使用PUT _template/{name}。
一、索引管理
创建索引
PUT my_index查看索引
GET my_index删除索引
DELETE my_index二、映射(Mapping)
创建索引并指定 mapping
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"userId": { "type": "integer" },
"userName": { "type": "text" },
"createTime": { "type": "date", "format": "yyyy-MM-dd||epoch_millis" }
}
}
}
}提示
6.x 中字段类型一旦确定,不可直接修改;需要重建索引(见下文重建思路)
获取 mapping
GET my_index/_mapping忽略不合法字段(ignore_malformed)
PUT my_index/_mapping/_doc
{
"properties": {
"boolean_field": {
"type": "boolean",
"ignore_malformed": true
}
}
}提示
当写入的值与字段类型不匹配时,不让整条文档写入失败,而是“忽略这个字段”的索引/存储,文档仍成功写入
三、文档管理
新增
自动生成 id
POST my_index/_doc
{
"userId": 1002,
"userName": "Alice"
}指定 id,如果文档存在则覆盖
PUT my_index/_doc/1
{
"userId": 1001,
"userName": "MaRui",
"createTime": "2023-07-01"
}查询
根据 id 查询
GET my_index/_doc/1修改
修改文档指定字段内容
POST my_index/_doc/1/_update
{
"doc": {
"userName": "MaRui-Updated"
}
}删除
根据 id 删除
DELETE my_index/_doc/1提示
Elasticsearch 6.2.4 使用 /{index}/{type}/{id} 或 /{index}/_doc/{id} 路径风格。
四、搜索(Search)
全量搜索
GET my_index/_search条件搜索(match/match_phrase)
GET my_index/_search
{
"query": {
"match": {
"userName": "MaRui"
}
}
}GET my_index/_search
{
"query": {
"match_phrase": {
"userName": "MaRui"
}
}
}过滤 + 排序 + 分页
GET my_index/_search
{
"query": {
"bool": {
"filter": [
{ "term": { "userId": 1001 } }
]
}
},
"sort": [ { "createTime": "desc" } ],
"from": 0,
"size": 10
}六、批量操作(Bulk)
按行提交,操作行与数据行成对出现,操作指令分别是创建 bulk_demo/_doc 文档、修改文档、根据 id 删除文档
POST _bulk
{"index":{"_index":"bulk_demo","_type":"_doc","_id":"1"}}
{"id":1,"name":"MaRui"}
{"update":{"_index":"bulk_demo","_type":"_doc","_id":"1"}}
{"doc":{"name":"MaRui88"}}
{"delete":{"_index":"bulk_demo","_type":"_doc","_id":"1"}}七、并发控制(版本控制)
在 6.2.4 中,乐观锁主要依赖 _version,读取文档,查看 _version
GET my_index/_doc/1基于版本的更新(version 参数)
PUT my_index/_doc/1?version=7
{
"userId": 1001,
"userName": "MaRui",
"createTime": "2023-07-01"
}若服务器端当前版本与请求 version 不一致,会返回 version_conflict_engine_exception
提示
_seq_no 与 _primary_term 在 6.2.4 默认不可用,6.3.0 以后才作为并发控制的主流方式。
八、路由(Routing)
为将相同业务主键路由至相同分片,可强制要求 _routing
PUT route_demo
{
"settings": { "number_of_shards": 3, "number_of_replicas": 1 },
"mappings": {
"_doc": {
"_routing": { "required": true },
"properties": {
"id": { "type": "integer" },
"name": { "type": "text" }
}
}
}
}写入/查询/删除均需携带 routing 参数
POST route_demo/_doc/1?routing=10
{ "id": 1, "name": "MaRui" }
GET route_demo/_doc/1?routing=10
DELETE route_demo/_doc/1?routing=10九、别名(Alias)
添加 log_001、log_002 文档
PUT log_001/_doc/1
{ "api":"/login", "method":"post" }
PUT log_002/_doc/2
{ "api":"/logout", "method":"post" }为多个索引设置同一别名,统一查询入口
POST /_aliases
{
"actions": [
{ "add": { "index": "log_001", "alias": "logs" }},
{ "add": { "index": "log_002", "alias": "logs" }}
]
}通过别名查询文档
GET logs/_search十、索引模板(Index Template)
为名称匹配某模式的索引自动应用一套预定义规则,做到一键统一配置,免去每次手动设置
PUT _template/app-log-template
{
"index_patterns": [ "app-log-*" ],
"settings": { "number_of_shards": 5, "number_of_replicas": 2 },
"mappings": {
"_doc": {
"properties": {
"create_time": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" },
"url": { "type": "text" },
"method": { "type": "keyword" }
}
}
},
"aliases": { "app-log-alias": {} },
"order": 200,
"version": 1
}查询索引模板
GET _template/app-log-template添加文档数据
PUT app-log-0001/_doc/1
{ "create_time":"2023-10-11 23:00:00", "url":"/login", "method":"post" }查询映射
GET app-log-0001通过别名查询数据
GET app-log-alias/_search十一、索引重建(Reindex)
字段/分片需变更时,创建新索引(调整分片/字段类型)
PUT my_index_v2
{
"settings": { "number_of_shards": 3, "number_of_replicas": 2 },
"mappings": {
"_doc": {
"properties": {
"userId": { "type": "integer" },
"userName": { "type": "keyword" }
}
}
}
}从旧索引复制数据
POST _reindex
{
"source": { "index": "my_index" },
"dest": { "index": "my_index_v2" }
}迁移完成后,可切换别名指向新索引,平滑替换
十二、分析器(Analyzer)
POST _analyze
{
"analyzer": "standard",
"text": "Hello. I'm 马瑞. nice to meet u."
}standard(标准分析器)、simple(简单分析器)、whitespace(空格分析器)。中文建议安装 IK 分词器(需与 ES 版本匹配的插件)。
十三、常用诊断命令
# 健康/状态
GET _cluster/health
GET _cat/indices?v
GET _cat/nodes?v
# 索引段与合并
POST my_index/_forcemerge?max_num_segments=1
# 刷新/同步
POST my_index/_refresh
POST my_index/_flush十四、聚合(Aggregations)
6.2.4 常用聚合示例:
统计总数/最大/最小/平均/求和
GET my_index/_search
{
"size": 0,
"aggs": {
"cnt": { "value_count": { "field": "userId" } },
"max_id": { "max": { "field": "userId" } },
"min_id": { "min": { "field": "userId" } },
"avg_id": { "avg": { "field": "userId" } },
"sum_id": { "sum": { "field": "userId" } }
}
}术语聚合(terms)- 类似 group by
GET my_index/_search
{
"size": 0,
"aggs": {
"by_name": {
"terms": {
"field": "userName.keyword",
"size": 10
}
}
}
}日期直方图(date_histogram)
GET my_index/_search
{
"size": 0,
"aggs": {
"by_day": {
"date_histogram": {
"field": "createTime",
"interval": "day",
"format": "yyyy-MM-dd"
}
}
}
}4) 嵌套聚合:先 terms 再度量
GET my_index/_search
{
"size": 0,
"aggs": {
"by_name": {
"terms": { "field": "userName.keyword" },
"aggs": {
"max_id": { "max": { "field": "userId" } }
}
}
}
}十五、滚动查询(Scroll)- 深翻页
说明:Scroll 适合批量拉取大量数据,不用于实时搜索排序。使用步骤:创建 scroll 上下文 -> 反复依据 scroll_id 拉取 -> 清理上下文。
初始化 Scroll 上下文
scroll=1m 表示为本次搜索创建一个 Scroll 上下文,并把它的“保持有效时间”设置为 1 分钟。也就是这次搜索的游标在 1 分钟内不会过期,便于你用返回的 _scroll_id 继续批量拉取下一页数据
GET my_index/_search?scroll=1m
{
"size": 1000,
"query": { "match_all": {} }
}响应中会返回 _scroll_id 与第一批数据。
继续拉取
POST _search/scroll
{
"scroll": "1m",
"scroll_id": "返回的_scroll_id"
}无更多数据时 hits.hits 为空。
清理 Scroll 上下文(推荐)
DELETE _search/scroll
{
"scroll_id": ["返回的_scroll_id1", "返回的_scroll_id2"]
}十六、Java 客户端示例(RestHighLevelClient,6.2.4)
6.2.4 推荐使用 High Level REST Client(与 ES 7 早期类似接口)。
1) 依赖(Maven)
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.2.4</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.2.4</version>
</dependency>2) 客户端初始化与关闭
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
public class EsClientProvider {
public static RestHighLevelClient create() {
return new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
}
}3) 索引文档(Index)
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
RestHighLevelClient client = EsClientProvider.create();
IndexRequest req = new IndexRequest("my_index", "_doc", "1")
.source("{\"userId\":1001,\"userName\":\"MaRui\"}", XContentType.JSON);
IndexResponse resp = client.index(req);
System.out.println(resp.getResult());
client.close();4) 获取文档(Get)
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
RestHighLevelClient client = EsClientProvider.create();
GetRequest get = new GetRequest("my_index", "_doc", "1");
GetResponse res = client.get(get);
if (res.isExists()) {
System.out.println(res.getSourceAsString());
}
client.close();5) 更新文档(Update)
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
RestHighLevelClient client = EsClientProvider.create();
UpdateRequest up = new UpdateRequest("my_index", "_doc", "1")
.doc("{\"userName\":\"MaRui-Updated\"}", XContentType.JSON);
UpdateResponse ur = client.update(up);
System.out.println(ur.getResult());
client.close();6) 删除文档(Delete)
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
RestHighLevelClient client = EsClientProvider.create();
DeleteRequest del = new DeleteRequest("my_index", "_doc", "1");
DeleteResponse dr = client.delete(del);
System.out.println(dr.getResult());
client.close();7) 搜索(Search)
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;
RestHighLevelClient client = EsClientProvider.create();
SearchSourceBuilder ssb = new SearchSourceBuilder()
.query(QueryBuilders.matchQuery("userName", "MaRui"))
.from(0).size(10);
SearchRequest sr = new SearchRequest("my_index").types("_doc").source(ssb);
SearchResponse resp = client.search(sr);
System.out.println(resp.getHits().getTotalHits());
client.close();8) 聚合查询(terms + max)
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.max.Max;
RestHighLevelClient client = EsClientProvider.create();
SearchSourceBuilder ssb = new SearchSourceBuilder().size(0)
.aggregation(
AggregationBuilders.terms("by_name").field("userName.keyword")
.subAggregation(AggregationBuilders.max("max_id").field("userId"))
);
SearchRequest req = new SearchRequest("my_index").types("_doc").source(ssb);
SearchResponse resp = client.search(req);
Terms terms = resp.getAggregations().get("by_name");
for (Terms.Bucket b : terms.getBuckets()) {
Max max = b.getAggregations().get("max_id");
System.out.println(b.getKeyAsString() + " -> " + (long) max.getValue());
}
client.close();9) Scroll 示例(批量拉取)
import org.elasticsearch.action.search.*;
import org.elasticsearch.common.unit.TimeValue;
RestHighLevelClient client = EsClientProvider.create();
final Scroll scroll = new Scroll(TimeValue.timeValueMinutes(1));
SearchRequest searchRequest = new SearchRequest("my_index").types("_doc");
SearchSourceBuilder ssb = new SearchSourceBuilder()
.query(QueryBuilders.matchAllQuery())
.size(1000);
searchRequest.source(ssb);
searchRequest.scroll(scroll);
SearchResponse searchResponse = client.search(searchRequest);
String scrollId = searchResponse.getScrollId();
SearchHit[] hits = searchResponse.getHits().getHits();
while (hits != null && hits.length > 0) {
for (SearchHit hit : hits) {
// 处理数据
}
SearchScrollRequest scrollRequest = new SearchScrollRequest(scrollId);
scrollRequest.scroll(scroll);
searchResponse = client.searchScroll(scrollRequest);
scrollId = searchResponse.getScrollId();
hits = searchResponse.getHits().getHits();
}
// 清理
ClearScrollRequest clear = new ClearScrollRequest();
clear.addScrollId(scrollId);
client.clearScroll(clear);
client.close();REST API 请求方法
GET(读取,幂等)
- 语义:获取资源,不修改数据
- 常见用法:
- 索引/文档/集群状态查询:
GET my_index、GET my_index/_doc/1、GET _cat/indices?v - 搜索:
GET my_index/_search(支持带请求体) - 映射/设置查看:
GET my_index/_mapping
- 索引/文档/集群状态查询:
- 使用场景:任何纯查询场景,需要可缓存、可重复请求
PUT(创建或整体替换,幂等)
- 语义:按照给定
ID创建,若存在则整体替换 - 常见用法:
- 创建索引:
PUT my_index - 固定
ID写入文档:PUT my_index/_doc/1 - 修改索引可变设置:
PUT my_index/_settings - 索引模板(6.x):
PUT _template/app-log-template
- 创建索引:
- 使用场景:有目标
ID/资源名”,且希望结果可重复执行(同结果)
POST(创建/执行动作,非幂等,也常用于需要请求体的查询)
- 语义:新增或触发一个操作
- 常见用法:
- 自动 ID 新增:
POST my_index/_doc - 部分更新:
POST my_index/_doc/1/_update - 批量操作:
POST _bulk - 重建索引:
POST _reindex - 滚动查询翻页:
POST _search/scroll - 搜索:
POST my_index/_search(常用于复杂请求体)
- 自动 ID 新增:
- 使用场景:自动
ID新增、调用API(update/bulk/reindex等)、携带复杂请求体的查询
DELETE(删除,幂等)
- 语义:删除资源
- 常见用法:
- 删除文档:
DELETE my_index/_doc/1 - 删除索引:
DELETE my_index - 清理滚动上下文:
DELETE _search/scroll
- 删除文档:
- 使用场景:移除索引/文档/
scroll等资源