Elasticsearch 版本演进

[!info] 数据来源
本文参考 Elasticsearch 官方文档(Elasticsearch 7.x Reference、8.x Reference、9.x Release Notes)及 elastic/elasticsearch-java 官方仓库。客户端 API 示例代码来源为官方文档的 Context7 实时索引。


一、版本演进全景图

版本 发布时间 Java 客户端 重大变化
0.90.x 2013 org.elasticsearch:elasticsearch:0.90.x 早期节点客户端(Node Client)
1.x 2014 TransportClient 兴起 支持 gateway、discovery
2.x 2015 TransportClient + Jest 移除 “groovy”lang scripting
5.x 2016 TransportClient + Low-level REST Client Ingest Node、Painless Scripting
6.x 2017 TransportClient 完善 + REST Client 稀疏字段支持、Index Sorting、跨集群搜索CCR
7.x 2019 HighLevelRestClient + TransportClient(deprecated) 移除了 types、革兰茨集群协调、JDK 11 内置
8.x 2022 全新 Java Clientco.elastic.clients TransportClient 完全移除、类型安全 API
9.x 2024 co.elastic.clients:elasticsearch-java:9.x 强制 Java 17+

二、各版本详细解析

2.1 Elasticsearch 2.x —— 规范化时代的起点

客户端选择:TransportClient(通过 9300 端口,传输协议通信)

1
2
3
4
5
6
7
8
9
10
11
12
<!-- Maven -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.16</version> <!-- 5.x 最后兼容 2.x 集群的版本 -->
<exclusions>
<exclusion>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
</exclusion>
</exclusions>
</dependency>

[!warning] 版本陷阱
Transport Client 5.x 版本使用 序列化的内部协议,与 2.x 集群不兼容。如需连接 2.x 集群,请使用 org.elasticsearch:elasticsearch:2.4.6 配合对应版本的 Transport Client。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.transport.client.TransportClient;
import org.elasticsearch.common.transport.InetSocketTransportAddress;

TransportClient transportClient = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(
new InetSocketAddress("localhost", 9300)
));

// 查询
SearchResponse response = transportClient.prepareSearch("my_index")
.setQuery(QueryBuilders.matchQuery("title", "elasticsearch"))
.setSize(10)
.get();

// 使用完毕后手动关闭
transportClient.close();

核心特性

  • 支持 Groovy、Python、JavaScript 等脚本语言(后因安全问题移除)
  • DELETE /{index}/{type}/{id} 格式的三段式 API

2.2 Elasticsearch 5.x —— REST Client 的诞生

重大变化

  • Ingest Node(数据预处理管道)
  • Painless Scripting(替代 Groovy,安全性大幅提升)
  • BWC索引格式(不再兼容 2.x 索引)
  • 新特性:join 字段类型、wildcard 字段类型

客户端演进

1
2
3
4
5
6
<!-- 低级别 REST Client(跨版本可用,兼容 ES 5.x ~ 7.x 集群) -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>5.6.16</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient; // ES 6.3+ 才有

// 低级别 REST Client
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")
).build();

// 查询示例(手动构建 JSON)
Map<String, String> params = Collections.singletonMap("pretty", "true");
Response response = restClient.performRequest("GET", "/my_index/_search", params);
System.out.println(EntityUtils.toString(response.getEntity()));

// 关闭
restClient.close();

特性:低级别 REST Client 只负责 HTTP 通信,不解析响应,无任何领域知识,可连接任意版本的 ES 集群。


2.3 Elasticsearch 6.x —— HighLevelRestClient 登场

重大变化

  • 移除了 indexdeletebulk API 中的 content-type 类型映射({type} 路径参数废弃)
  • Index Sorting(索引内字段排序)
  • Cross-Cluster Search(CCS)和 Cross-Cluster Replication(CCR)正式发布
  • 稀疏字段(sparse_vector field type)

HighLevelRestClient(Maven)

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>6.8.24</version> <!-- 6.x 最后一个版本,连接 6.x 集群 -->
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>6.8.24</version>
</dependency>

[!tip] 版本对应关系
HighLevelRestClient 7.17.x 版本可以连接 7.x 集群。客户端版本号与集群版本号对齐。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;

// 初始化(ES 6.x)
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("localhost", 9200, "http"),
new HttpHost("localhost", 9201, "http")
)
);

// 同步查询(ES 6.x 方式)
SearchRequest searchRequest = new SearchRequest("my_index");
searchRequest.source(SearchSourceBuilderBuilder
.query(QueryBuilders.matchQuery("title", "elasticsearch"))
);
searchRequest.size(10);

SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);

// 遍历结果
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}

// 异步查询
client.searchAsync(searchRequest, RequestOptions.DEFAULT,
new ActionListener<SearchResponse>() {
@Override
public void onResponse(SearchResponse response) { /* ... */ }
@Override
public void onFailure(Exception e) { /* ... */ }
}
);

// 关闭
client.close();

2.4 Elasticsearch 7.x —— Type 消亡与 TransportClient 废弃

最重大的变化

  1. 移除了 Type:索引从 {index}/{type}/{id} 变成了 {index}/_doc/{id},一个索引只能有一种 mapping type
  2. 革兰茨集群协调(Cluster coordination):移除了 minimum_master_nodes,使用革兰茨法定人数算法
  3. JDK 11 内置:ES 7.x 自带 OpenJDK 11,不再依赖系统 JDK
  4. HighLevelRestClient 正式登场(基于 REST Client,提供了领域对象封装)
  5. Search Templates:更优雅的搜索模板管理

HighLevelRestClient 7.17.x(Maven)

1
2
3
4
5
6
7
8
9
10
11
<!-- ES 7.x 推荐版本:7.17.x(7.x 最后一个 LTS 子版本) -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.17.16</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>7.17.16</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.core.MainResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.builder.SearchSourceBuilder;

// 初始化(ES 7.x - HighLevelRestClient)
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
"http://localhost:9200",
"http://localhost:9201"
)
);

// 获取集群信息
MainResponse info = client.info(RequestOptions.DEFAULT);
System.out.println("集群名: " + info.getClusterName());
System.out.println("ES版本: " + info.getVersion().getNumber());

// === 索引操作 ===
// 创建索引
client.indices().create(
new CreateIndexRequest("my_index"),
RequestOptions.DEFAULT
);

// === 文档操作 ===
// 单条写入
IndexRequest request = new IndexRequest("my_index");
request.id("1");
request.source(
"user", "kimchy",
"message", "trying out Elasticsearch",
"date", LocalDate.now().toString()
);
IndexResponse response = client.index(request, RequestOptions.DEFAULT);

// === 批量写入 ===
BulkRequest bulkRequest = new BulkRequest();
bulkRequest.add(new IndexRequest("my_index").id("2").source("user", "test", "message", "bulk demo"));
bulkRequest.add(new IndexRequest("my_index").id("3").source("user", "dev", "message", "another doc"));
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);

// === 查询 ===
SearchRequest searchRequest = new SearchRequest("my_index");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("message", "Elasticsearch"));
sourceBuilder.from(0).size(10);
searchRequest.source(sourceBuilder);

SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
System.out.println("命中: " + searchResponse.getHits().getTotalHits());
Arrays.stream(searchResponse.getHits().getHits())
.forEach(hit -> System.out.println(hit.getSourceAsMap()));

// === 聚合查询 ===
sourceBuilder.aggregation(
AggregationBuilders.terms("top_users").field("user.keyword").size(5)
);
searchRequest.source(sourceBuilder);

// 关闭
client.close();

[!warning] TransportClient 被标记为 deprecated
ES 7.15 起TransportClient 正式被标记为废弃(@Deprecated),官方推荐迁移到 HighLevelRestClient。ES 8.x 完全移除了 TransportClient


2.5 Elasticsearch 8.x —— 全新 Java Client(颠覆性重写)

重大变化

  1. 全新 Java Client(co.elastic.clients:elasticsearch-java

    • 完全重写,API 设计与 REST Client 完全不同
    • 强类型 API(strongly-typed),编译期类型安全
    • 使用 Builder 模式替代构造函数链
    • 移除了 TransportClient
    • 移除了 HighLevelRestClient
  2. 默认开启安全:HTTPS 强制启用,TLS 证书验证默认开启

  3. Rollup API 正式发布:时序数据聚合

  4. Searchable Snapshots:可搜索快照

  5. **强制 Java 17+**(部分功能)

新 Java Client 8.x(Maven)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!-- ES 8.x 全新官方 Java 客户端 -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.15.0</version>
</dependency>

<!-- 必须依赖:底层 HTTP 客户端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>8.15.0</version>
</dependency>

<!-- 可选:JSON 序列化支持(Jackson 或 EPL) -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>

[!tip] 版本兼容性规则(官方定义)
Java Client 向前兼容(forward compatible):8.12 客户端可以连接 8.12、8.13、8.14…… 等于或更高的 ES 集群。但 8.12 客户端不支持 8.13 集群新增的功能特性,需要升级客户端版本才能使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.api.security.ApiKey;

// === 初始化(ES 8.x - 全新 API) ===

// 方式一:Basic Auth + TLS
ElasticsearchClient client = ElasticsearchClient.of(b -> b
.host("https://localhost:9200")
.usernameAndPassword("elastic", "password")
.sslContext(sslContext) // 需要配置 TLS
);

// 方式二:API Key(推荐用于生产)
ElasticsearchClient client = ElasticsearchClient.of(b -> b
.host("https://localhost:9200")
.apiKey("VnVhQ2ZHY0JDZGJrU...") // 从 Kibana 获取
);

// 方式三:使用 RestClientTransport(完整控制)
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "https")
).build();

ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper()
);

ElasticsearchClient esClient = new ElasticsearchClient(transport);

// === 索引操作 ===
esClient.indices().create(c -> c.index("my_index"));

// === 文档操作 ===
// 写入
esClient.index(i -> i
.index("my_index")
.id("1")
.document(new User("kimchy", "trying out Elasticsearch", LocalDate.now()))
);

// 批量写入
BulkOperation op1 = BulkOperation.of(b -> b
.index(i -> i.index("my_index").id("2").document(new User("test", "bulk doc", LocalDate.now())))
);
BulkOperation op2 = BulkOperation.of(b -> b
.index(i -> i.index("my_index").id("3").document(new User("dev", "another doc", LocalDate.now())))
);
BulkResponse bulk = esClient.bulk(b -> b.operations(op1, op2));

// === 查询(Lambda 语法,强类型) ===
SearchResponse<User> response = esClient.search(s -> s
.index("my_index")
.query(q -> q
.match(m -> m.field("message").query("Elasticsearch"))
)
.size(10),
User.class
);

// 遍历结果
for (Hit<User> hit : response.hits().hits()) {
User user = hit.source();
System.out.println(user.user() + ": " + user.message());
}

// === 聚合查询 ===
SearchResponse<Void> aggResponse = esClient.search(s -> s
.index("my_index")
.size(0)
.aggregations("top_users", a -> a
.terms(t -> t.field("user.keyword").size(5))
),
Void.class
);

TermsAggregate topUsers = aggResponse.aggregations().get("top_users").sterms();
topUsers.buckets().array().forEach(bucket ->
System.out.println(bucket.key().stringValue() + ": " + bucket.docCount())
);

// 关闭
esClient.close();
restClient.close();

// User record 类定义
public record User(String user, String message, LocalDate date) {}

2.6 Elasticsearch 9.x —— Java 17 强制时代

重大变化

  1. **强制 Java 17+**(项目必须从 JDK 8/11 升级)
  2. 移除了旧版 RestClientorg.elasticsearch.client:elasticsearch-rest-client 不再维护)
  3. 最小支持 ES 集群版本:7.x
  4. 移除了 deprecated API:部分 8.x 中标记为废弃的功能被清理

ES 9.x Java Client(Maven)

1
2
3
4
5
6
7
8
9
10
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>9.0.0</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>9.0.0</version>
</dependency>

[!warning] ES 9.x 迁移注意事项
ES 9.x 的客户端包名虽然仍是 co.elastic.clients:elasticsearch-java,但 API 有 break change

  • 部分方法的参数签名发生了变化
  • 需要重新阅读官方迁移指南

三、客户端版本选择对照表

1
2
3
4
5
6
7
8
┌─────────────┬──────────────────────────────┬──────────────────────────────┬─────────────────┐
│ 集群版本 │ 推荐客户端 │ Maven GroupId │ 是否推荐 │
├─────────────┼──────────────────────────────┼──────────────────────────────┼─────────────────┤
│ ES 6.x │ HighLevelRestClient 6.8.x │ org.elasticsearch.client │ ❌ 已停止维护 │
│ ES 7.x │ HighLevelRestClient 7.17.x │ org.elasticsearch.client │ ⚠️ 过渡期使用 │
│ ES 8.x │ Java Client 8.x │ co.elastic.clients │ ✅ 当前主流 │
│ ES 9.x │ Java Client 9.x │ co.elastic.clients │ ✅ 最新推荐 │
└─────────────┴──────────────────────────────┴──────────────────────────────┴─────────────────┘

[!tip] 客户端选择建议

  • 新项目:直接使用 ES 8.x 集群 + Java Client 8.x
  • 存量项目:从 HighLevelRestClient 7.17 逐步迁移到 Java Client 8.x
  • 切忌:不要混用客户端版本和集群版本,如 7.x 集群不要用 8.x 的 HighLevelRestClient

四、核心 API 一览

4.1 文档 CRUD

操作 ES 7.x(HighLevelRestClient) ES 8.x(全新 Java Client)
索引文档 client.index(request) client.index(fn)
批量写入 client.bulk(request) client.bulk(fn)
获取文档 client.get(request) client.get(fn)
删除文档 client.delete(request) client.delete(fn)
更新文档 client.update(request) client.update(fn)
批量读取 client.mget(request) client.mget(fn)

4.2 搜索 API

操作 ES 7.x ES 8.x
全文搜索 QueryBuilders.matchQuery() q.match(fn)
精确匹配 QueryBuilders.termQuery() q.term(fn)
多条件查询 QueryBuilders.boolQuery() q.bool(fn)
范围查询 QueryBuilders.rangeQuery() q.range(fn)
高亮 HighlightBuilder s.highlight(fn)
聚合 AggregationBuilders s.aggregations(fn)
分页 from/size s.from/s.size

4.3 索引管理

操作 ES 7.x ES 8.x
创建索引 client.indices().create() client.indices().create(fn)
删除索引 client.indices().delete() client.indices().delete(fn)
刷新索引 client.indices().refresh() client.indices().refresh(fn)
mapping client.indices().putMapping() client.indices().putMapping(fn)
别名管理 client.indices().putAlias() client.indices().putAlias(fn)

五、常见问题

Q1:HighLevelRestClient 和全新的 Java Client 有什么区别?

对比项 HighLevelRestClient(7.x) 全新 Java Client(8.x+)
包名 org.elasticsearch.client co.elastic.clients
API 风格 方法链(builder 模式) Lambda Builder(函数式)
类型安全 基于 Map / Object 返回 强类型 + 泛型,编译期校验
依赖 REST Client + Jackson REST Client + Jackson
异步支持 *Async 方法 + ActionListener 原生 CompletableFuture
TransportClient 使用 已移除

Q2:ES 8.x 的 REST Client 还能用吗?

可以。org.elasticsearch.client:elasticsearch-rest-client:8.x 仍然可用(底层通信层),但 HighLevelRestClient 已完全移除。全新 Java Client 8.x 封装了 REST Client,提供更友好的 API。

Q3:Spring Boot 项目如何集成?

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- Spring Boot 2.7.x + ES 7.x -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>2.7.18</version> <!-- 最后支持 ES 7.x 的版本 -->
</dependency>

<!-- Spring Boot 3.x + ES 8.x -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>3.2.x</version>
</dependency>

[!tip] Spring Boot 版本对应
Spring Boot 2.7.x → Elasticsearch 7.x
Spring Boot 3.x → Elasticsearch 8.x(依赖 Spring Data Elasticsearch 5.x)

注意:Spring Data Elasticsearch 版本与 ES 版本独立,维护自己的兼容矩阵。


六、版本演进总结

1
2
3
4
5
6
7
8
2013   ES 0.90        →  Node Client / TransportClient
2014 ES 1.x → Gateway / Discovery 模块
2015 ES 2.x → 移除 Groovy Scripting
2016 ES 5.x → Ingest Node + Painless + REST Client
2017 ES 6.x → HighLevelRestClient 登场,Type 废除倒计时
2019 ES 7.x → Types 彻底移除,TransportClient 废弃
2022 ES 8.x → 全新 Java Client,强制 HTTPS
2024 ES 9.x → 强制 Java 17,生态全面现代化

参考资料