-
什么是RestClient
RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。
RestClient 主要特点
-
轻量级:只负责 HTTP 通信,不包含高级功能
-
兼容性好:支持所有 Elasticsearch 版本
-
灵活性强:可以自定义请求和响应处理
-
线程安全:可以被多线程共享使用
-
性能优秀:内置连接池和失败重试机制
ES中支持两种地理坐标数据类型 : geo_point:由纬度(latitude)和经度(longitude)确定的一个点。
例如:"32.8752345,120.2981576 geo_shape:有多个geo_point组成的复杂几何图形。例如一条直线 "LINESTRING(-77.03653 38.897676,-77.009051 38.889939)
字段拷贝可以使用copy_to属性将当前字段拷贝到指定字段。用来解决多个搜索字段共同搜索时的效率问题示例:
"all":{ "type":"text", "analyzer":"ik_max_word" }, "brand":{ "type":"keyword", "copy_to":"all" }
-
-
初始化RestClient
创建
ElasticsearchUtil.java
工具类:import org.apache.http.HttpHost; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestClientBuilder; import org.elasticsearch.client.RestHighLevelClient; public class ElasticsearchUtil { private static RestHighLevelClient client; public static void init() { // 配置ES集群地址,可以配置多个 RestClientBuilder builder = RestClient.builder( new HttpHost("localhost", 9200, "http") // 可以添加更多节点 // new HttpHost("localhost", 9201, "http") ); // 可选:配置连接超时、认证等 builder.setRequestConfigCallback(requestConfigBuilder -> { return requestConfigBuilder .setConnectTimeout(5000) // 连接超时时间 .setSocketTimeout(60000); // 套接字超时时间 }); client = new RestHighLevelClient(builder); } public static RestHighLevelClient getClient() { if (client == null) { init(); } return client; } public static void close() { if (client != null) { try { client.close(); } catch (Exception e) { e.printStackTrace(); } } } }
创建索引的操作
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest; import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest; import org.elasticsearch.action.admin.indices.get.GetIndexRequest; import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContentType; import java.io.IOException; public class IndexOperations { private static final String INDEX_NAME = "products"; public static void main(String[] args) throws IOException { RestHighLevelClient client = ElasticsearchUtil.getClient(); // 创建索引 createIndex(client); // 检查索引是否存在 boolean exists = checkIndexExists(client); System.out.println("索引是否存在: " + exists); // 删除索引 // deleteIndex(client); ElasticsearchUtil.close(); } public static void createIndex(RestHighLevelClient client) throws IOException { CreateIndexRequest request = new CreateIndexRequest(INDEX_NAME); // 索引设置 request.settings(Settings.builder() .put("index.number_of_shards", 3) .put("index.number_of_replicas", 1) ); // 映射定义 String mapping = "{\n" + " \"properties\": {\n" + " \"id\": {\"type\": \"keyword\"},\n" + " \"name\": {\n" + " \"type\": \"text\",\n" + " \"analyzer\": \"ik_max_word\",\n" + " \"fields\": {\"keyword\": {\"type\": \"keyword\"}}\n" + " },\n" + " \"price\": {\"type\": \"double\"},\n" + " \"stock\": {\"type\": \"integer\"},\n" + " \"create_time\": {\"type\": \"date\"}\n" + " }\n" + "}"; request.mapping("_doc", mapping, XContentType.JSON); client.indices().create(request, RequestOptions.DEFAULT); System.out.println("索引创建成功"); } public static boolean checkIndexExists(RestHighLevelClient client) throws IOException { GetIndexRequest request = new GetIndexRequest(); request.indices(INDEX_NAME); return client.indices().exists(request, RequestOptions.DEFAULT); } public static void deleteIndex(RestHighLevelClient client) throws IOException { DeleteIndexRequest request = new DeleteIndexRequest(INDEX_NAME); client.indices().delete(request, RequestOptions.DEFAULT); System.out.println("索引删除成功"); } }
文档CRUD操作
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class DocumentOperations {
private static final String INDEX_NAME = "products";
private static final ObjectMapper mapper = new ObjectMapper();
public static void main(String[] args) throws IOException {
RestHighLevelClient client = ElasticsearchUtil.getClient();
// 添加文档
String docId = createDocument(client);
// 查询文档
getDocument(client, docId);
// 更新文档
updateDocument(client, docId);
// 删除文档
// deleteDocument(client, docId);
ElasticsearchUtil.close();
}
public static String createDocument(RestHighLevelClient client) throws IOException {
// 准备文档数据
Map<String, Object> document = new HashMap<>();
document.put("id", "1001");
document.put("name", "华为手机 P40");
document.put("price", 4999.00);
document.put("stock", 100);
document.put("create_time", new Date());
// 创建索引请求
IndexRequest request = new IndexRequest(INDEX_NAME)
.id(document.get("id").toString()) // 文档ID
.source(mapper.writeValueAsString(document), XContentType.JSON);
// 执行请求
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
if (response.getResult() == DocWriteResponse.Result.CREATED) {
System.out.println("文档创建成功, ID: " + response.getId());
} else if (response.getResult() == DocWriteResponse.Result.UPDATED) {
System.out.println("文档更新成功, ID: " + response.getId());
}
return response.getId();
}
public static void getDocument(RestHighLevelClient client, String docId) throws IOException {
GetRequest request = new GetRequest(INDEX_NAME, docId);
GetResponse response = client.get(request, RequestOptions.DEFAULT);
if (response.isExists()) {
System.out.println("获取文档成功: " + response.getSourceAsString());
} else {
System.out.println("文档不存在");
}
}
public static void updateDocument(RestHighLevelClient client, String docId) throws IOException {
// 准备更新内容
Map<String, Object> updateFields = new HashMap<>();
updateFields.put("price", 4599.00);
updateFields.put("stock", 80);
UpdateRequest request = new UpdateRequest(INDEX_NAME, docId)
.doc(mapper.writeValueAsString(updateFields), XContentType.JSON);
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println("文档更新成功, 版本号: " + response.getVersion());
}
public static void deleteDocument(RestHighLevelClient client, String docId) throws IOException {
DeleteRequest request = new DeleteRequest(INDEX_NAME, docId);
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
if (response.getResult() == DocWriteResponse.Result.DELETED) {
System.out.println("文档删除成功");
} else if (response.getResult() == DocWriteResponse.Result.NOT_FOUND) {
System.out.println("文档不存在");
}
}
}
搜索操作:重点在于如何构建查询的条件
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import java.io.IOException;
public class SearchOperations {
private static final String INDEX_NAME = "products";
public static void main(String[] args) throws IOException {
RestHighLevelClient client = ElasticsearchUtil.getClient();
// 简单匹配查询
searchByMatch(client);
// 范围查询
// searchByRange(client);
ElasticsearchUtil.close();
}
public static void searchByMatch(RestHighLevelClient client) throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
// 构建查询条件
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.matchQuery("name", "华为手机"));
// 设置分页
sourceBuilder.from(0);
sourceBuilder.size(10);
request.source(sourceBuilder);
// 执行查询
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println("命中总数: " + response.getHits().getTotalHits().value);
System.out.println("查询耗时(ms): " + response.getTook().getMillis());
for (SearchHit hit : response.getHits().getHits()) {
System.out.println("文档ID: " + hit.getId() + ", 内容: " + hit.getSourceAsString());
}
}
public static void searchByRange(RestHighLevelClient client) throws IOException {
SearchRequest request = new SearchRequest(INDEX_NAME);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(QueryBuilders.rangeQuery("price").gte(4000).lte(5000));
request.source(sourceBuilder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println("价格在4000-5000之间的商品:");
for (SearchHit hit : response.getHits().getHits()) {
System.out.println(hit.getSourceAsString());
}
}
}
批量进行操作
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
public class BulkOperations {
private static final String INDEX_NAME = "products";
public static void main(String[] args) throws IOException {
RestHighLevelClient client = ElasticsearchUtil.getClient();
// 准备批量数据
List<String> products = Arrays.asList(
"{\"id\":\"1002\",\"name\":\"小米手机10\",\"price\":3999.00,\"stock\":50}",
"{\"id\":\"1003\",\"name\":\"iPhone 12\",\"price\":6299.00,\"stock\":30}",
"{\"id\":\"1004\",\"name\":\"OPPO Find X2\",\"price\":4999.00,\"stock\":40}"
);
BulkRequest request = new BulkRequest();
// 添加多个操作到批量请求
for (String product : products) {
String id = extractId(product); // 从JSON中提取ID
request.add(new IndexRequest(INDEX_NAME)
.id(id)
.source(product, XContentType.JSON));
}
// 执行批量操作
BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
if (response.hasFailures()) {
System.out.println("批量操作有部分失败: " + response.buildFailureMessage());
} else {
System.out.println("批量操作全部成功");
}
ElasticsearchUtil.close();
}
private static String extractId(String json) {
// 简单实现,实际应用中应该使用JSON解析
return json.split("\"id\":\"")[1].split("\"")[0];
}
}
RestClient 提供了灵活而强大的方式来与 Elasticsearch 交互,虽然需要编写更多代码,但也提供了更精细的控制能力。对于大多数 Java 应用程序来说,这是与 Elasticsearch 集成的可靠选择。