本文目录导读:

在 Java 中操作 Elasticsearch 索引,通常有两种主流方式:
- Spring Data Elasticsearch:推荐用于 Spring Boot 项目,更符合 Spring 的编程习惯。
- Elasticsearch Java Client (8.x):官方原生客户端,功能全面,性能好。
我将分别展示这两种方式创建和删除索引的案例,以 Elasticsearch 8.x 版本为例。
前置准备:依赖与客户端连接
无论哪种方式,都需要先连接 ES 服务器。
Maven 依赖
<!-- 1. Spring Data Elasticsearch -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>3.2.0</version>
</dependency>
<!-- 2. 官方 Java Client -->
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.12.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
使用 Spring Data Elasticsearch
这种方式通过@Document注解和ElasticsearchOperations模板类操作索引。
定义实体类(同时也是索引映射)
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
// 定义索引名为 "user_index",分片数1,副本数0
@Document(indexName = "user_index", shards = 1, replicas = 0)
public class UserDocument {
@Id
private String id;
@Field(type = FieldType.Text, analyzer = "ik_smart") // 指定分词器
private String name;
@Field(type = FieldType.Integer)
private Integer age;
@Field(type = FieldType.Keyword)
private String email;
// Getters & Setters
public String getId() { return id; }
public void setId(String id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
}
创建和删除索引的实现
import org.elasticsearch.client.RestHighLevelClient; // 注意:Spring Data 3.x 底层已使用新客户端
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.IndexOperations;
import org.springframework.stereotype.Service;
@Service
public class IndexService {
@Autowired
private ElasticsearchOperations elasticsearchOperations;
/**
* 创建索引(基于@Document注解的配置)
* 如果索引已存在,Spring Data 默认会忽略或报错,这里处理为安全创建。
*/
public boolean createIndex() {
// 获取针对 UserDocument 类的索引操作对象
IndexOperations indexOps = elasticsearchOperations.indexOps(UserDocument.class);
// 检查索引是否存在
if (!indexOps.exists()) {
// 创建索引并应用映射
boolean created = indexOps.create();
System.out.println("索引创建成功: " + created);
return created;
} else {
System.out.println("索引已存在,跳过创建");
return true; // 返回 true 表示索引可用
}
}
/**
* 删除索引
*/
public boolean deleteIndex() {
IndexOperations indexOps = elasticsearchOperations.indexOps(UserDocument.class);
boolean deleted = indexOps.delete();
System.out.println("索引删除成功: " + deleted);
return deleted;
}
}
调用示例
// 在 Controller 或测试类中注入 IndexService @Autowired private IndexService indexService; // 创建 indexService.createIndex(); // 删除 indexService.deleteIndex();
使用官方 Java Client (8.x)
这种方式更底层,需要手动构建 JSON 格式的映射(Mapping)和设置(Settings)。
创建索引
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.CreateIndexRequest;
import co.elastic.clients.elasticsearch.indices.CreateIndexResponse;
import co.elastic.clients.elasticsearch.indices.DeleteIndexRequest;
import co.elastic.clients.elasticsearch.indices.DeleteIndexResponse;
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.Header;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.elasticsearch.client.RestClient;
import java.io.IOException;
public class IndexManager {
private ElasticsearchClient client;
// 构建客户端连接
public IndexManager() {
// 1. 创建 RestClient
BasicCredentialsProvider credsProv = new BasicCredentialsProvider();
credsProv.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "your_password")
);
RestClient restClient = RestClient.builder(new HttpHost("localhost", 9200, "https"))
.setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credsProv)
)
.build();
// 2. 创建 Transport
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
// 3. 创建 Client
this.client = new ElasticsearchClient(transport);
}
/**
* 创建索引(包含 Mapping 和 Settings)
*/
public boolean createIndexWithMapping() throws IOException {
String indexName = "product_index";
// 检查索引是否存在
boolean exists = client.indices().exists(e -> e.index(indexName)).value();
if (exists) {
System.out.println("索引 [" + indexName + "] 已存在");
return true;
}
// 创建索引请求
CreateIndexRequest request = new CreateIndexRequest.Builder()
.index(indexName)
.settings(s -> s
.numberOfShards("3")
.numberOfReplicas("1")
)
.mappings(m -> m
.properties("name", p -> p.text(t -> t.analyzer("standard"))) // 标准分词
.properties("price", p -> p.double_(d -> d))
.properties("tags", p -> p.keyword(k -> k))
.properties("createdAt", p -> p.date(d -> d.format("yyyy-MM-dd HH:mm:ss")))
)
.build();
// 执行创建
CreateIndexResponse response = client.indices().create(request);
boolean acknowledged = response.acknowledged();
System.out.println("索引 [" + indexName + "] 创建结果: " + acknowledged);
return acknowledged;
}
/**
* 删除索引
*/
public boolean deleteIndex() throws IOException {
String indexName = "product_index";
// 检查是否存在
boolean exists = client.indices().exists(e -> e.index(indexName)).value();
if (!exists) {
System.out.println("索引 [" + indexName + "] 不存在,无法删除");
return false;
}
// 删除索引
DeleteIndexResponse response = client.indices().delete(d -> d.index(indexName));
boolean acknowledged = response.acknowledged();
System.out.println("索引 [" + indexName + "] 删除结果: " + acknowledged);
return acknowledged;
}
// 关闭连接
public void close() throws IOException {
if (client != null) {
client._transport().close();
}
}
}
调用示例
IndexManager manager = new IndexManager();
try {
// 创建
manager.createIndexWithMapping();
// 删除
manager.deleteIndex();
} catch (IOException e) {
e.printStackTrace();
} finally {
manager.close();
}
总结与对比
| 特性 | Spring Data Elasticsearch | 官方 Java Client (8.x) |
|---|---|---|
| 代码简洁性 | ⭐⭐⭐⭐⭐ (注解驱动) | ⭐⭐⭐ (需要手写映射) |
| 灵活性 | ⭐⭐⭐ (依赖注解约定) | ⭐⭐⭐⭐⭐ (完全控制) |
| 推荐场景 | Spring Boot 项目,标准 CRUD | 需要精细控制 Mapping/Settings |
| Mapping 定义 | 实体类注解自动生成 | 手动构建 Builder 或 JSON |
建议:
- 如果是 Spring Boot 项目,优先选择 Spring Data Elasticsearch,你只需定义好实体类(如
@Document)和 Repository 接口,索引操作由框架自动处理。 - 如果你需要精细控制索引的 Mapping、Settings(如指定自定义分词器、复杂的字段类型),或者你的项目不是基于 Spring,推荐使用 官方 Java Client。