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 Client(co.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
| <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>transport</artifactId> <version>5.6.16</version> <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
| <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;
RestClient restClient = RestClient.builder( new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 9201, "http") ).build();
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 登场
重大变化:
- 移除了
index、delete、bulk 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> </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;
RestHighLevelClient client = new RestHighLevelClient( RestClient.builder( new HttpHost("localhost", 9200, "http"), new HttpHost("localhost", 9201, "http") ) );
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 废弃
最重大的变化:
- 移除了 Type:索引从
{index}/{type}/{id} 变成了 {index}/_doc/{id},一个索引只能有一种 mapping type
- 革兰茨集群协调(Cluster coordination):移除了
minimum_master_nodes,使用革兰茨法定人数算法
- JDK 11 内置:ES 7.x 自带 OpenJDK 11,不再依赖系统 JDK
- HighLevelRestClient 正式登场(基于 REST Client,提供了领域对象封装)
- Search Templates:更优雅的搜索模板管理
HighLevelRestClient 7.17.x(Maven):
1 2 3 4 5 6 7 8 9 10 11
| <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;
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(颠覆性重写)
重大变化:
全新 Java Client(co.elastic.clients:elasticsearch-java):
- 完全重写,API 设计与 REST Client 完全不同
- 强类型 API(strongly-typed),编译期类型安全
- 使用 Builder 模式替代构造函数链
- 移除了 TransportClient
- 移除了 HighLevelRestClient
默认开启安全:HTTPS 强制启用,TLS 证书验证默认开启
Rollup API 正式发布:时序数据聚合
Searchable Snapshots:可搜索快照
**强制 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
| <dependency> <groupId>co.elastic.clients</groupId> <artifactId>elasticsearch-java</artifactId> <version>8.15.0</version> </dependency>
<dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-client</artifactId> <version>8.15.0</version> </dependency>
<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;
ElasticsearchClient client = ElasticsearchClient.of(b -> b .host("https://localhost:9200") .usernameAndPassword("elastic", "password") .sslContext(sslContext) );
ElasticsearchClient client = ElasticsearchClient.of(b -> b .host("https://localhost:9200") .apiKey("VnVhQ2ZHY0JDZGJrU...") );
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));
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();
public record User(String user, String message, LocalDate date) {}
|
2.6 Elasticsearch 9.x —— Java 17 强制时代
重大变化:
- **强制 Java 17+**(项目必须从 JDK 8/11 升级)
- 移除了旧版 RestClient(
org.elasticsearch.client:elasticsearch-rest-client 不再维护)
- 最小支持 ES 集群版本:7.x
- 移除了 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
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-elasticsearch</artifactId> <version>2.7.18</version> </dependency>
<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,生态全面现代化
|
参考资料