Elasticsearch 版本演进与 Java 客户端接入完全指南
!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 端口,传输协议通信)
xml
<!-- 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。
java
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字段类型
客户端演进:
xml
<!-- 低级别 REST Client(跨版本可用,兼容 ES 5.x ~ 7.x 集群) -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>5.6.16</version>
</dependency>
java
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 登场
重大变化:
- 移除了
index、delete、bulkAPI 中的content-type类型映射({type}路径参数废弃) - Index Sorting(索引内字段排序)
- Cross-Cluster Search(CCS)和 Cross-Cluster Replication(CCR)正式发布
- 稀疏字段(
sparse_vectorfield type)
HighLevelRestClient(Maven):
xml
<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 集群。客户端版本号与集群版本号对齐。
java
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 废弃
最重大的变化:
- 移除了 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):
xml
<!-- 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>
java
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(颠覆性重写)
重大变化:
-
全新 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):
xml
<!-- 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 集群新增的功能特性,需要升级客户端版本才能使用。
java
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 强制时代
重大变化:
- 强制 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):
xml
<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:
- 部分方法的参数签名发生了变化
- 需要重新阅读官方迁移指南
三、客户端版本选择对照表
arduino
┌─────────────┬──────────────────────────────┬──────────────────────────────┬─────────────────┐
│ 集群版本 │ 推荐客户端 │ 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 项目如何集成?
xml
<!-- 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 版本独立,维护自己的兼容矩阵。
六、版本演进总结
yaml
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,生态全面现代化