RestClient
-
什么是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中提取IDrequest.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 集成的可靠选择。