目录
- Elasticsearch 简介
- 环境准备
- 使用 Java 连接 Elasticsearch
- 基本 CRUD 操作
- 复杂查询操作
- 索引管理与优化
- 聚合操作
- 总结
1. Elasticsearch 简介
Elasticsearch 是一个分布式搜索和分析引擎,基于 Apache Lucene 构建,能够实现实时数据的存储、搜索、和分析。它广泛应用于全文搜索、日志分析、性能监控等领域。Elasticsearch 的核心概念包括文档(document)、索引(index)、和分片(shard)。
2. 环境准备
2.1 安装 Elasticsearch
从 Elasticsearch 官方网站 下载并安装适合你操作系统的版本。
安装完成后,通过以下命令启动 Elasticsearch 服务:
./bin/elasticsearch
默认情况下,Elasticsearch 运行在 http://localhost:9200
。
2.2 Java 开发环境配置
- 安装 Java SDK(JDK 11 或更高版本)。
- 安装 Maven 或 Gradle。
- 创建一个 Maven 项目,添加 Elasticsearch Java 客户端的依赖。
2.3 添加 Elasticsearch 客户端依赖
在 Maven 项目的 pom.xml
文件中添加以下依赖:
<dependencies>
<!-- Elasticsearch Java Client -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.10.0</version>
</dependency>
</dependencies>
如果你使用 Gradle,可以在 build.gradle
文件中添加以下依赖:
dependencies {
implementation 'co.elastic.clients:elasticsearch-java:8.10.0'
}
添加依赖后,确保项目能够正常编译。
3. 使用 Java 连接 Elasticsearch
接下来,我们将编写一个简单的 Java 程序来连接 Elasticsearch。
3.1 编写连接代码
创建一个 Java 类,例如 ElasticsearchConnection.java
,并编写以下代码:
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.InfoResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
public class ElasticsearchConnection {
public static void main(String[] args) throws Exception {
// 创建 REST 客户端
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
// 创建传输层
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
// 创建 Elasticsearch 客户端
ElasticsearchClient client = new ElasticsearchClient(transport);
// 获取集群信息
InfoResponse info = client.info();
System.out.println("Connected to Elasticsearch cluster: " + info.clusterName());
// 关闭客户端
transport.close();
}
}
3.2 运行代码
编译并运行这个程序,如果成功,你将看到类似如下的输出:
Connected to Elasticsearch cluster: elasticsearch
这表明你已经成功连接到了 Elasticsearch。
4. 基本 CRUD 操作
Elasticsearch 的 CRUD 操作主要涉及对索引中的文档进行增(Create)、查(Read)、改(Update)、删(Delete)操作。
4.1 创建索引和插入文档
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.IndexResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.IndexRequest;
public class ElasticsearchCRUD {
public static void main(String[] args) throws Exception {
// 创建 REST 客户端
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
// 创建传输层
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
// 创建 Elasticsearch 客户端
ElasticsearchClient client = new ElasticsearchClient(transport);
// 创建文档
String json = "{ \"name\": \"John Doe\", \"age\": 30, \"city\": \"New York\" }";
// 插入文档到索引
IndexRequest<Object> request = new IndexRequest.Builder<>()
.index("users")
.id("1")
.document(json)
.build();
IndexResponse response = client.index(request);
System.out.println("Document inserted with ID: " + response.id());
// 关闭客户端
transport.close();
}
}
4.2 查询文档
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.GetResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.GetRequest;
public class ElasticsearchRead {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 查询文档
GetRequest getRequest = new GetRequest.Builder()
.index("users")
.id("1")
.build();
GetResponse<Object> response = client.get(getRequest, Object.class);
if (response.found()) {
System.out.println("Document found: " + response.source());
} else {
System.out.println("Document not found");
}
transport.close();
}
}
4.3 更新文档
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.UpdateResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.UpdateRequest;
import java.util.Map;
public class ElasticsearchUpdate {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 更新文档
Map<String, Object> updateJson = Map.of(
"age", 31,
"city", "San Francisco"
);
UpdateRequest<Object, Map<String, Object>> updateRequest = new UpdateRequest.Builder<>()
.index("users")
.id("1")
.doc(updateJson)
.build();
UpdateResponse<Object> updateResponse = client.update(updateRequest, Object.class);
System.out.println("Document updated: " + updateResponse.result());
transport.close();
}
}
4.4 删除文档
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.DeleteResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.DeleteRequest;
public class ElasticsearchDelete {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 删除文档
DeleteRequest deleteRequest = new DeleteRequest.Builder()
.index("users")
.id("1")
.build();
DeleteResponse deleteResponse = client.delete(deleteRequest);
System.out.println("Document deleted: " + deleteResponse.result());
transport.close();
}
}
5. 复杂查询操作
Elasticsearch 提供了强大的查询 DSL(Domain Specific Language),支持布尔查询、范围查询、聚合查询等。
5.1 布尔查询
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.search.Query;
public class ElasticsearchBooleanQuery {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 布尔查询
SearchRequest searchRequest = new SearchRequest.Builder()
.index("users")
.query(Query
.bool(b -> b
.must(m -> m.match(match -> match.field("name").query("John Doe")))
.filter(f -> f.range(r -> r.field("age").gte(30)))
))
.build();
SearchResponse<Object> searchResponse = client.search(searchRequest, Object.class);
for (Hit<Object> hit : searchResponse.hits().hits()) {
System.out.println("Document found: " + hit.source());
}
transport.close();
}
}
5.2 范围查询
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.search.Query;
public class ElasticsearchRangeQuery {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 范围查询:查询 age 在 25 到 35 之间的文档
SearchRequest searchRequest = new SearchRequest.Builder()
.index("users")
.query(Query.range(r -> r.field("age").gte(25).lte(35)))
.build();
SearchResponse<Object> searchResponse = client.search(searchRequest, Object.class);
for (Hit<Object> hit : searchResponse.hits().hits()) {
System.out.println("Document found: " + hit.source());
}
transport.close();
}
}
6. 索引管理与优化
在 Elasticsearch 中,索引管理是非常重要的操作,合理的索引设置和优化可以大幅提升查询性能。
6.1 创建索引并设置映射
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
public class ElasticsearchCreateIndex {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 创建索引并设置映射
CreateIndexRequest createIndexRequest = new CreateIndexRequest.Builder()
.index("users")
.mappings(m -> m
.properties("name", p -> p.text(t -> t))
.properties("age", p -> p.integer(i -> i))
.properties("city", p -> p.text(t -> t))
)
.build();
CreateIndexResponse createIndexResponse = client.indices().create(createIndexRequest);
if (createIndexResponse.acknowledged()) {
System.out.println("Index created successfully!");
}
transport.close();
}
}
6.2 删除索引
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
public class ElasticsearchDeleteIndex {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 删除索引
DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder()
.index("users")
.build();
DeleteIndexResponse deleteIndexResponse = client.indices().delete(deleteIndexRequest);
if (deleteIndexResponse.acknowledged()) {
System.out.println("Index deleted successfully!");
}
transport.close();
}
}
7. 聚合操作
Elasticsearch 的聚合功能非常强大,能够对数据进行分组统计、计算平均值、最大值、最小值等操作。
7.1 聚合查询:计算年龄的平均值
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.Aggregation;
import co.elastic.clients.elasticsearch.core.search.Bucket;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
public class ElasticsearchAggregation {
public static void main(String[] args) throws Exception {
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http")).build();
RestClientTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
ElasticsearchClient client = new ElasticsearchClient(transport);
// 聚合查询:计算年龄的平均值
SearchRequest searchRequest = new SearchRequest.Builder()
.index("users")
.size(0) // 不返回文档,只返回聚合结果
.aggregations("average_age", a -> a.avg(avg -> avg.field("age")))
.build();
SearchResponse<Object> searchResponse = client.search(searchRequest, Object.class);
double averageAge = searchResponse.aggregations().get("average_age").avg().value();
System.out.println("Average age: " + averageAge);
transport.close();
}
}
8. 总结
本教程详细介绍了如何在 Java 中使用 Elasticsearch,涵盖了连接、基本 CRUD 操作、复杂查询、索引管理和聚合操作等方面的内容。通过这些示例,开发者可以一步步地掌握如何在 Java 项目中集成 Elasticsearch,并利用其强大的搜索和分析功能来构建高效的应用程序。