二、環(huán)境準(zhǔn)備
在開始之前,確保我們已經(jīng)在本地或服務(wù)器上成功安裝并運行了 Elasticsearch 8.X。同時,我們的開發(fā)環(huán)境需要具備以下條件:
Java 版本:JDK 1.8 或更高版本
依賴庫:Elasticsearch Java API Client
在 pom.xml 文件中添加以下依賴:
<project xmlns="http://maven./POM/4.0.0" xmlns:xsi="http://www./2001/XMLSchema-instance" xsi:schemaLocation="http://maven./POM/4.0.0 http://maven./xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mingyi.cn</groupId>
<artifactId>ESJavaClient</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.11.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.3</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>
</project>
三、Elasticsearch 客戶端初始化
1. 基于 HTTPS 的客戶端初始化
Elasticsearch 8.X 默認(rèn)開啟了安全特性,需要通過 HTTPS 進(jìn)行通信。以下是初始化客戶端的主要步驟:
設(shè)置認(rèn)證信息:使用用戶名和密碼進(jìn)行身份驗證。

配置 SSL 上下文:創(chuàng)建 SSLContext,用于 HTTP 客戶端構(gòu)建。
// 設(shè)置用戶名和密碼
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "your_password"));
// 加載 CA 證書
Path caCertificatePath = Paths.get("path/to/http_ca.crt");
CertificateFactory factory = CertificateFactory.getInstance("X.509");
Certificate trustedCa;
try (InputStream is = Files.newInputStream(caCertificatePath)) {
trustedCa = factory.generateCertificate(is);
}
// 配置 SSL 上下文
KeyStore trustStore = KeyStore.getInstance("pkcs12");
trustStore.load(null, null);
trustStore.setCertificateEntry("ca", trustedCa);
SSLContextBuilder sslContextBuilder = SSLContexts.custom()
.loadTrustMaterial(trustStore, null);
final SSLContext sslContext = sslContextBuilder.build();
// 構(gòu)建 RestClient
RestClientBuilder builder = RestClient.builder(
new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
.setSSLContext(sslContext)
.setDefaultCredentialsProvider(credentialsProvider)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE));
RestClient restClient = builder.build();
// 創(chuàng)建 Elasticsearch 客戶端
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
2. 使用 API Key 的客戶端初始化(可選)
如果希望使用 API Key 進(jìn)行認(rèn)證,可以按照以下方式配置:
String apiKeyId = "your_api_key_id";
String apiKeySecret = "your_api_key_secret";
String apiKeyAuth = Base64.getEncoder().encodeToString(
(apiKeyId + ":" + apiKeySecret).getBytes(StandardCharsets.UTF_8));
Header[] defaultHeaders = {
new BasicHeader("Authorization", "ApiKey " + apiKeyAuth)
};
builder.setDefaultHeaders(defaultHeaders);
四、基本操作示例
1. 創(chuàng)建索引
public void createIndex(String indexName) throws IOException {
client.indices().create(c -> c.index(indexName));
}
2. 索引文檔
public void indexDocument(String indexName, String id, Map<String, Object> document) throws IOException {
client.index(i -> i.index(indexName).id(id).document(document));
}
3. 搜索文檔
public SearchResponse<Object> search(String indexName, List<Query> queries, List<SortOptions> sortOptions, int page, int pageSize) throws IOException {
SearchRequest.Builder searchRequestBuilder = new SearchRequest.Builder()
.index(indexName)
.from(page * pageSize)
.size(pageSize)
.query(q -> q.bool(b -> b.must(queries)));
if (sortOptions != null && !sortOptions.isEmpty()) {
searchRequestBuilder.sort(sortOptions);
}
return client.search(searchRequestBuilder.build(), Object.class);
}
4. 聚合查詢
public SearchResponse<Object> aggregateSearch(String indexName, List<Query> queries, Map<String, Aggregation> aggregations) throws IOException {
return client.search(s -> s
.index(indexName)
.query(q -> q.bool(b -> b.must(queries)))
.aggregations(aggregations), Object.class);
}
5. 腳本排序示例
public SearchResponse<Map> searchWithScriptSort(String indexName, String fieldName, String queryText, String scriptSource, double factor) throws IOException {
Query query = MatchQuery.of(m -> m.field(fieldName).query(queryText))._toQuery();
Script script = Script.of(s -> s.inline(i -> i
.source(scriptSource)
.params("factor", JsonData.of(factor))));
SortOptions sortOptions = SortOptions.of(so -> so.script(ss -> ss
.script(script)
.type(ScriptSortType.Number)
.order(SortOrder.Asc)));
SearchRequest searchRequest = new SearchRequest.Builder()
.index(indexName)
.query(query)
.sort(sortOptions)
.build();
return client.search(searchRequest, Map.class);
}
五、完整代碼示例
以下是完整的代碼示例,大家可以根據(jù)需要進(jìn)行替換和修改,以適應(yīng)咱們自己的工程需求。
public class ElasticsearchService {
private static final Logger logger = LoggerFactory.getLogger(ElasticsearchService.class);
private ElasticsearchClient client;
// 構(gòu)造函數(shù),初始化客戶端
public ElasticsearchService() throws CertificateException, IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
// 初始化代碼(參考前文)
}
// 創(chuàng)建索引
public void createIndex(String indexName) throws IOException {
client.indices().create(c -> c.index(indexName));
}
// 索引文檔
public void indexDocument(String indexName, String id, Map<String, Object> document) throws IOException {
client.index(i -> i.index(indexName).id(id).document(document));
}
// 搜索文檔
public SearchResponse<Object> search(...) throws IOException {
// 實現(xiàn)代碼(參考前文)
}
// 聚合查詢
public SearchResponse<Object> aggregateSearch(...) throws IOException {
// 實現(xiàn)代碼(參考前文)
}
// 腳本排序示例
public SearchResponse<Map> searchWithScriptSort(...) throws IOException {
// 實現(xiàn)代碼(參考前文)
}
// 主方法示例
public static void main(String[] args) {
try {
ElasticsearchService service = new ElasticsearchService();
String indexName = "my-index";
// 創(chuàng)建索引
service.createIndex(indexName);
// 索引文檔
Map<String, Object> document = new HashMap<>();
document.put("title", "Elasticsearch Basics");
document.put("author", "John Doe");
document.put("content", "This is a tutorial for Elasticsearch.");
service.indexDocument(indexName, "1", document);
logger.info("Document indexed.");
// 刷新索引
service.client.indices().refresh(r -> r.index(indexName));
// 搜索示例
Query query = QueryBuilders.match(m -> m.field("title").query("Elasticsearch"));
List<Query> queries = Arrays.asList(query);
SearchResponse<Object> response = service.search(indexName, queries, null, 0, 10);
response.hits().hits().forEach(hit -> logger.info(hit.source().toString()));
// 聚合查詢示例
Aggregation aggregation = AggregationBuilders.terms(t -> t.field("author.keyword"));
Map<String, Aggregation> aggMap = new HashMap<>();
aggMap.put("author_count", aggregation);
SearchResponse<Object> aggResponse = service.aggregateSearch(indexName, queries, aggMap);
aggResponse.aggregations().forEach((key, agg) -> logger.info(key + ": " + agg));
// 腳本排序示例
String scriptSource = "doc['content.keyword'].value.length() * params.factor";
double factor = 1.1;
SearchResponse<Map> scriptSortResponse = service.searchWithScriptSort(indexName, "content", "Elasticsearch", scriptSource, factor);
scriptSortResponse.hits().hits().forEach(hit -> logger.info(hit.source().toString()));
} catch (Exception e) {
logger.error("Error occurred:", e);
}
}
}
六、注意事項
6.1 認(rèn)證方式
Elasticsearch 8.X 默認(rèn)開啟了安全認(rèn)證,我們需要根據(jù)實際情況選擇使用用戶名密碼認(rèn)證或 API Key 認(rèn)證。
6.2 SSL 證書
確保正確加載了 Elasticsearch 提供的 CA 證書,以建立安全的 SSL 連接。
6.3 依賴版本
請確保使用的 Elasticsearch Java API Client 版本與 Elasticsearch 服務(wù)器版本匹配。
七、總結(jié)
本文詳細(xì)介紹了如何使用 Elasticsearch 8.X 的最新 Java API 進(jìn)行客戶端初始化、索引操作、搜索和聚合查詢。
通過完整的代碼示例,我們可以直接將其應(yīng)用于工程開發(fā)中。希望本文能對大家在使用 Elasticsearch 進(jìn)行開發(fā)時提供幫助。

執(zhí)行成果截圖

新寫入索引數(shù)據(jù)

完整可用工程下載地址:https://t./yLZmm
七、參考資料
- Elasticsearch Java API Client 官方文檔https://www./guide/en/elasticsearch/client/java-api-client/current/index.html