RestClient

  1. 什么是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"
    }
  1. 初始化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 集成的可靠选择。

相关推荐
能工智人小辰24 分钟前
二刷苍穹外卖 day02
java
亲爱的非洲野猪1 小时前
基于ElasticSearch的法律法规检索系统架构实践
大数据·elasticsearch·系统架构
你的人类朋友2 小时前
🤔Token 存储方案有哪些
前端·javascript·后端
烛阴2 小时前
从零开始:使用Node.js和Cheerio进行轻量级网页数据提取
前端·javascript·后端
liuyang___2 小时前
日期的数据格式转换
前端·后端·学习·node.js·node
bxlj_jcj2 小时前
深入剖析Debezium:CDC领域的“数据魔法棒”
java·架构
叶 落3 小时前
ubuntu 安装 JDK8
java·ubuntu·jdk·安装·java8
爱学习的白杨树3 小时前
Sentinel介绍
java·开发语言
XW3 小时前
java mcp client调用 (modelcontextprotocol)
java·llm
保持学习ing4 小时前
SpringBoot前后台交互 -- 登录功能实现(拦截器+异常捕获器)
java·spring boot·后端·ssm·交互·拦截器·异常捕获器