1. 引入依赖(Maven)
需保证客户端版本与 ES 服务器版本一致:
xml
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.10.0</version> <!-- 与ES服务器版本一致 -->
</dependency>
<!-- 依赖Jackson处理JSON -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
2. 配置 ES 连接
创建客户端实例,配置 ES 集群地址、认证信息等:
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 org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
public class ESClientConfig {
public static ElasticsearchClient getClient() {
// 1. 创建REST客户端(配置ES集群地址,可多个)
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200, "http"), // 节点1
new HttpHost("localhost", 9201, "http") // 节点2(集群时配置)
).build();
// 2. 创建传输层(关联REST客户端和JSON处理器)
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper()
);
// 3. 创建ES客户端(核心操作入口)
return new ElasticsearchClient(transport);
}
}
如果 ES 开启了安全认证(如账号密码),需在 RestClient 中添加认证拦截器:
java
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
// 在RestClient.builder()前添加认证
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "your-password"));
RestClient restClient = RestClient.builder(...)
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
.build();
3. 核心功能实现
(1)索引管理(创建 / 删除索引)
java
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.ElasticsearchIndicesClient;
public class IndexManager {
private final ElasticsearchClient client = ESClientConfig.getClient();
private final ElasticsearchIndicesClient indicesClient = client.indices();
// 创建索引(含映射配置)
public void createIndex(String indexName) throws Exception {
// 定义映射(以"product"索引为例:id、name、price、createTime字段)
String mapping = "{\n" +
" "properties": {\n" +
" "id": { "type": "keyword" },\n" +
" "name": { "type": "text", "analyzer": "ik_max_word" },\n" +
" "price": { "type": "double" },\n" +
" "createTime": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss" }\n" +
" }\n" +
"}";
CreateIndexRequest request = CreateIndexRequest.of(b -> b
.index(indexName)
.mappings(m -> m.withJson(new StringReader(mapping)))
);
indicesClient.create(request);
System.out.println("索引创建成功:" + indexName);
}
// 删除索引
public void deleteIndex(String indexName) throws Exception {
indicesClient.delete(d -> d.index(indexName));
System.out.println("索引删除成功:" + indexName);
}
}
(2)文档操作(增删改查)
假设存在实体类Product
:
java
import com.fasterxml.jackson.annotation.JsonFormat;
import java.util.Date;
public class Product {
private String id;
private String name;
private Double price;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date createTime;
// getter/setter 省略
}
文档操作示例:
java
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.search.Hit;
public class DocumentService {
private final ElasticsearchClient client = ESClientConfig.getClient();
private static final String INDEX_NAME = "product";
// 新增文档(自动生成ID)
public void addDocument(Product product) throws Exception {
IndexRequest<Product> request = IndexRequest.of(b -> b
.index(INDEX_NAME)
.document(product)
);
IndexResponse response = client.index(request);
System.out.println("新增文档ID:" + response.id());
}
// 根据ID查询文档
public Product getDocumentById(String id) throws Exception {
GetRequest request = GetRequest.of(b -> b.index(INDEX_NAME).id(id));
GetResponse<Product> response = client.get(request, Product.class);
return response.found() ? response.source() : null;
}
// 更新文档(全量更新)
public void updateDocument(String id, Product product) throws Exception {
UpdateRequest<Product, Product> request = UpdateRequest.of(b -> b
.index(INDEX_NAME)
.id(id)
.doc(product)
);
client.update(request, Product.class);
}
// 删除文档
public void deleteDocument(String id) throws Exception {
DeleteRequest request = DeleteRequest.of(b -> b.index(INDEX_NAME).id(id));
client.delete(request);
}
}
(3)查询操作(全文检索、条件过滤等)
java
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.query_dsl.QueryBuilders;
import java.util.List;
import java.util.stream.Collectors;
public class SearchService {
private final ElasticsearchClient client = ESClientConfig.getClient();
private static final String INDEX_NAME = "product";
// 全文检索(搜索name中包含"手机"的商品)
public List<Product> searchByKeyword(String keyword) throws Exception {
SearchRequest request = SearchRequest.of(b -> b
.index(INDEX_NAME)
.query(q -> q
.match(m -> m
.field("name") // 检索字段
.query(keyword) // 检索关键词
)
)
);
SearchResponse<Product> response = client.search(request, Product.class);
return response.hits().hits().stream()
.map(Hit::source)
.collect(Collectors.toList());
}
// 条件过滤(价格大于1000的商品,分页查询)
public List<Product> searchByPrice(Double minPrice, int page, int size) throws Exception {
SearchRequest request = SearchRequest.of(b -> b
.index(INDEX_NAME)
.query(q -> q
.range(r -> r
.field("price")
.gt(minPrice) // 价格>minPrice
)
)
.from((page - 1) * size) // 分页起始位置
.size(size) // 每页条数
);
SearchResponse<Product> response = client.search(request, Product.class);
return response.hits().hits().stream()
.map(Hit::source)
.collect(Collectors.toList());
}
}
三、Spring Boot 项目中的简化实现(Spring Data Elasticsearch)
如果项目基于 Spring Boot,可使用spring-data-elasticsearch
简化配置:
- 引入依赖:
xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
- 配置 ES 地址(application.yml):
yaml
spring:
elasticsearch:
uris: http://localhost:9200,http://localhost:9201
username: elastic
password: your-password
- 定义 Repository 接口(类似 JPA):
java
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import java.util.List;
// Product实体类需添加@Document注解指定索引
@Document(indexName = "product")
public class Product { ... }
// 继承ElasticsearchRepository,自动实现CRUD方法
public interface ProductRepository extends ElasticsearchRepository<Product, String> {
// 自定义查询(根据name模糊查询)
List<Product> findByNameContaining(String keyword);
// 价格范围查询
List<Product> findByPriceGreaterThan(Double minPrice);
}
- 服务层直接注入使用:
java
@Service
public class ProductService {
@Autowired
private ProductRepository productRepository;
public void addProduct(Product product) {
productRepository.save(product);
}
public List<Product> searchByName(String keyword) {
return productRepository.findByNameContaining(keyword);
}
}