ES笔记:Java客户端基础使用

本文记录Java中使用ES客户端进行基础的索引和文档CRUD操作,客户端版本为8.1.0,具体操作直接看代码示例。

  • 索引CRUD
  • 文档CRUD
  • 文档条件查询
  • ES客户端异步执行

pom.xml配置

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yun.es.api</groupId>
    <artifactId>es8-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <elastic.version>8.1.0</elastic.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.elasticsearch.plugin</groupId>
            <artifactId>x-pack-sql-jdbc</artifactId>
            <version>8.1.0</version>
        </dependency>
        <dependency>
            <groupId>co.elastic.clients</groupId>
            <artifactId>elasticsearch-java</artifactId>
            <version>${elastic.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <dependency>
            <groupId>jakarta.json</groupId>
            <artifactId>jakarta.json-api</artifactId>
            <version>2.0.1</version>
        </dependency>
    </dependencies>
</project>

代码示例

package com.yun.es.api;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import co.elastic.clients.elasticsearch._types.query_dsl.Query;
import co.elastic.clients.elasticsearch.core.*;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.bulk.CreateOperation;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.elasticsearch.indices.ExistsRequest;
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.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;

import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.ArrayList;

/**
 * ES客户端索引、文档基础操作
 */
public class EsClient {
    /**
     * 同步操作客户端
     */
    private static ElasticsearchClient client;

    /**
     * 异步操作客户端
     */
    private static ElasticsearchAsyncClient asyncClient;

    /**
     * 数据传输对象
     */
    private static ElasticsearchTransport transport;

    /**
     * 同步操作索引名称
     */
    private static final String ES_TEST_001 = "es_test_001";

    /**
     * 异步操作异步索引名称
     */
    private static final String ES_ASYNC_TEST_001 = "es_async_test_001";

    public static void main(String[] args) throws Exception {
        // 初始化ES客户端
        initEsConnection();

        // 常用索引操作
        operateIndex();

        // 常用索引操作(采用lambda表达式实现)
        operateIndexLambda();

        // 常用文档操作
        operateDocument();

        // 常用文档操作(采用lambda表达式实现)
        operateDocumentLambda();

        // 查询文档
        queryDocument();

        // ES异步操作
        asyncOperation();
    }

    /**
     * 异步操作通过回调方法判断是否执行成功
     *
     * @throws Exception 操作失败
     */
    private static void asyncOperation() throws Exception {
        asyncClient.indices().create(req -> req.index(ES_ASYNC_TEST_001))
                // whenComplete中内容为异步执行的回调方法,不会阻塞主线程代码
                // 如果想开始执行后,不等回调方法就立马执行的操作,可以用thenApply方法
                // .thenApply(resp -> resp.acknowledged())
                .whenComplete(
                        (resp, error) -> {
                            System.out.println("异步操作回调方法");
                            if (resp != null) {
                                System.out.println(resp.acknowledged());
                            } else {
                                error.printStackTrace();
                            }
                        }
                );
        System.out.println("主线程方法");
    }

    /**
     * match查询示例,其他查询方式也非常好识别,根据查询方式找到对应类名和方法即可
     *
     * @throws Exception 操作失败
     */
    private static void queryDocument() throws Exception {
        // 使用match方式查询age=18的数据
        MatchQuery matchQuery = new MatchQuery.Builder()
                .field("age").query(18)
                .build();

        Query query = new Query.Builder()
                .match(matchQuery)
                .build();

        SearchRequest searchRequest = new SearchRequest.Builder()
                .query(query)
                .build();

        SearchResponse<Object> searchResponse = client.search(searchRequest, Object.class);
        transport.close();
    }

    /**
     * 使用lambda表达式简化文档操作
     *
     * @throws Exception 操作失败
     */
    private static void operateDocumentLambda() throws Exception {
        // 根据实例创建单个文档
        CreateResponse createResponse = client.create(req -> req
                .index(ES_TEST_001)
                .id("001")
                .document(new User(1, 18, "zhangsan")));

        // 批量创建文档
        ArrayList<BulkOperation> bulkOperations = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            CreateOperation<User> userCreateOperation = new CreateOperation.Builder<User>()
                    .index(ES_TEST_001)
                    .id(String.format("001%d", i))
                    .document(new User(1 + i, 18 + i, String.format("zhangsan%d", i)))
                    .build();
            BulkOperation bulkOperation = new BulkOperation.Builder().create(userCreateOperation).build();
            bulkOperations.add(bulkOperation);
        }
        BulkResponse bulkResponse = client.bulk(req -> req.operations(bulkOperations));

        // 删除文档
        DeleteResponse deleteResponse = client.delete(req -> req.index(ES_TEST_001).id("001"));

        transport.close();
    }


    /**
     * 基础文档操作
     *
     * @throws Exception 操作失败
     */
    private static void operateDocument() throws Exception {
        // 实例数据
        User user = new User();
        user.setId(1);
        user.setAge(18);
        user.setName("zhangsan");

        // 根据实例创建单个文档
        CreateRequest<User> userCreateRequest = new CreateRequest.Builder<User>()
                .index(ES_TEST_001)
                .id("001")
                .document(user)
                .build();
        CreateResponse createResponse = client.create(userCreateRequest);

        // 批量创建文档
        ArrayList<BulkOperation> bulkOperations = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            CreateOperation<User> userCreateOperation = new CreateOperation.Builder<User>()
                    .index(ES_TEST_001)
                    .id(String.format("001%d", i))
                    .document(new User(1 + i, 18 + i, String.format("zhangsan%d", i)))
                    .build();
            BulkOperation bulkOperation = new BulkOperation.Builder().create(userCreateOperation).build();
            bulkOperations.add(bulkOperation);
        }
        BulkRequest bulkRequest = new BulkRequest.Builder()
                .operations(bulkOperations)
                .build();
        BulkResponse bulkResponse = client.bulk(bulkRequest);

        // 删除文档
        DeleteRequest deleteRequest = new DeleteRequest.Builder()
                .index(ES_TEST_001)
                .id("001")
                .build();
        DeleteResponse deleteResponse = client.delete(deleteRequest);

        transport.close();
    }

    /**
     * 使用lambda简化索引操作
     *
     * @throws Exception 操作失败
     */
    private static void operateIndexLambda() throws Exception {
        final ElasticsearchIndicesClient indices = client.indices();

        // 判断索引是否存在
        final boolean flag = indices.exists(req -> req.index(ES_TEST_001)).value();
        if (flag) {
            System.out.println(String.format("索引%s已存在", ES_TEST_001));
        } else {
            // 创建索引
            indices.create(req -> req.index(ES_TEST_001));
            System.out.println(String.format("索引%s创建成功", ES_TEST_001));
        }

        // 查询索引
        GetIndexResponse getIndexResponse = indices.get(req -> req.index(ES_TEST_001));
        System.out.println(String.format("查询索引%s成功", ES_TEST_001));
        // 查看具体的索引信息
        // IndexState indexState = getIndexResponse.get(ES_TEST_001);

        // 删除索引
        DeleteIndexResponse deleteIndexResponse = indices.delete(req -> req.index(ES_TEST_001));
        System.out.println(String.format("删除索引%s成功: %b", ES_TEST_001, deleteIndexResponse.acknowledged()));

        transport.close();
    }

    /**
     * 基础索引操作
     *
     * @throws Exception 操作失败
     */
    private static void operateIndex() throws Exception {
        final ElasticsearchIndicesClient indices = client.indices();
        // 判断索引是否存在
        ExistsRequest existsRequest = new ExistsRequest.Builder().index(ES_TEST_001).build();
        final boolean flag = indices.exists(existsRequest).value();
        if (flag) {
            System.out.println(String.format("索引%s已存在", ES_TEST_001));
        } else {
            // 创建索引
            CreateIndexRequest indexRequest = new CreateIndexRequest.Builder().index(ES_TEST_001).build();
            CreateIndexResponse createIndexResponse = indices.create(indexRequest);
            System.out.println(String.format("索引%s创建成功", ES_TEST_001));
        }

        // 查询索引
        GetIndexRequest getIndexRequest = new GetIndexRequest.Builder().index(ES_TEST_001).build();
        GetIndexResponse getIndexResponse = indices.get(getIndexRequest);
        System.out.println(String.format("查询索引%s成功", ES_TEST_001));
        // 查看具体的索引信息
        // IndexState indexState = getIndexResponse.get(ES_TEST_001);

        // 删除索引
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(ES_TEST_001).build();
        DeleteIndexResponse deleteIndexResponse = indices.delete(deleteIndexRequest);
        System.out.println(String.format("删除索引%s成功: %b", ES_TEST_001, deleteIndexResponse.acknowledged()));

        transport.close();
    }

    /**
     * 使用证书创建ES客户端(是否进行证书认证,可根据实际使用配置)
     *
     * @throws Exception 操作失败
     */
    private static void initEsConnection() throws Exception {
        // 创建认证对象,包含ca证书路径、认证类型等信息
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials("elastic", "password"));
        Path caCertificatePath = Paths.get("ca.crt");
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Certificate trustedCa;
        try (InputStream is = Files.newInputStream(caCertificatePath)) {
            trustedCa = factory.generateCertificate(is);
        }
        KeyStore trustStore = KeyStore.getInstance("pkcs12");
        trustStore.load(null, null);
        trustStore.setCertificateEntry("ca", trustedCa);
        SSLContextBuilder sslContextBuilder = SSLContexts.custom().loadTrustMaterial(trustStore, null);
        final SSLContext sslContext = sslContextBuilder.build();

        // 自定义创建ES客户端
        RestClientBuilder builder = RestClient.builder(
                new HttpHost("linux01", 9200, "https"))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                        // 自定义客户端设置
                        return httpAsyncClientBuilder.setSSLContext(sslContext)
                                .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                                .setDefaultCredentialsProvider(credentialsProvider);
                    }
                });
        // ES客户端
        RestClient restClient = builder.build();
        // 数据参数对象
        transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
        // 同步操作客户端
        client = new ElasticsearchClient(transport);
        // 异步操作客户端
        asyncClient = new ElasticsearchAsyncClient(transport);
    }
}
posted @ 2024-02-06 01:27  山上下了雪-bky  阅读(31)  评论(0编辑  收藏  举报