Elasticsearch之JavaAPI操作ES

Posted 上善若泪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elasticsearch之JavaAPI操作ES相关的知识,希望对你有一定的参考价值。

1 JavaAPI

1.1 pom.xml

<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-client</artifactId>
    <version>7.9.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>7.9.0</version>
</dependency>
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>7.9.0</version>
</dependency>

1.2 示例Demo

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;

import java.io.IOException;

public class TestES4j 
    private static RestHighLevelClient client = new RestHighLevelClient(
            RestClient.builder(
                    new HttpHost("localhost", 9200, "http")
            ));

    public static void main(String[] args) throws IOException 
        String indexName = "test001";
        if(!checkExistIndex(indexName))
            createIndex(indexName);
        
        if(checkExistIndex(indexName))
            deleteIndex(indexName);
        
        checkExistIndex(indexName);
        client.close();
    

    private static boolean checkExistIndex(String indexName) throws IOException 
        boolean result =true;
        try 
            OpenIndexRequest openIndexRequest = new OpenIndexRequest(indexName);
            client.indices().open(openIndexRequest,RequestOptions.DEFAULT).isAcknowledged();

         catch (ElasticsearchStatusException ex) 
            String m = "type=index_not_found_exception, reason=no such index";
            if (ex.getMessage().contains(m)) 
                result = false;
            
        
        if(result)
            System.out.println("索引:" +indexName + " 是存在的");
        else
            System.out.println("索引:" +indexName + " 不存在");

        return result;

    

    private static void deleteIndex(String indexName) throws IOException 
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        client.indices().delete(request,RequestOptions.DEFAULT);
        System.out.println("删除了索引:"+indexName);

    

    private static void createIndex(String indexName) throws IOException 
        // TODO Auto-generated method stub
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        client.indices().create(request,RequestOptions.DEFAULT);
        System.out.println("创建了索引:"+indexName);
    

1.3 操作文档

用的的实体:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product 
    private int id;
    private String name;

主要操作逻辑

import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class TestESCrud 

    private static RestHighLevelClient client
            = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
    private static String indexName = "test001";

    public static void main(String[] args) throws Exception
		//校验索引和创建索引 同示例Demo,所以不在重复展出
        if(!checkExistIndex(indexName))//确保索引存在
            createIndex(indexName);
        

        Product product = new Product(); //准备数据
        product.setId(1);
        product.setName("product 1");

        addDocument(product);//增加文档

        getDocument(1); //获取文档

        product.setName("product 2"); //修改数据

        updateDocument(product);//修改文档

        getDocument(1); //获取文档

        deleteDocument(1); //删除文档

        getDocument(1); //获取文档

        client.close();
    

    private static void deleteDocument(int id) throws IOException 
        DeleteRequest  deleteRequest = new DeleteRequest(indexName, String.valueOf(id));

        client.delete(deleteRequest,RequestOptions.DEFAULT);
        System.out.println("已经从ElasticSearch服务器上删除id="+id+"的文档");
    

    private static void updateDocument(Product product) throws IOException 

        UpdateRequest updateRequest = new UpdateRequest (indexName, "product", String.valueOf(product.getId()))
                .doc("name",product.getName());

        client.update(updateRequest,RequestOptions.DEFAULT);
        System.out.println("已经在ElasticSearch服务器修改产品为:"+product);

    

    private static void getDocument(int id) throws IOException 
        // TODO Auto-generated method stub
        GetRequest request = new GetRequest(
                indexName,
                "product",
                String.valueOf(id));

        GetResponse response = client.get(request,RequestOptions.DEFAULT);

        if(!response.isExists())
            System.out.println("检查到服务器上 "+"id="+id+ "的文档不存在");
        
        else
            String source = response.getSourceAsString();
            System.out.print("获取到服务器上 "+"id="+id+ "的文档内容是:");
            System.out.println(source);
        
    

    private static void addDocument(Product product) throws IOException 
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("name", product.getName());
        IndexRequest indexRequest = new IndexRequest(indexName, "product", String.valueOf(product.getId()))
                .source(jsonMap);
        client.index(indexRequest,RequestOptions.DEFAULT);
        System.out.println("已经向ElasticSearch服务器增加产品:"+product);
    


注意:当在操作文档时,如果提示含有type的过时了,可把type参数去掉
点击了解Elasticsearch为什么要去除 表 type

1.4 批量操作文档

此时 需要另外引入的pom

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.83</version>
</dependency>

1.4.1 实体和工具类

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product 
    private int id;
    private String name;
    private String category;
    private float price;
    private String place;
    private String code;

工具类

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class ProductUtil 
    public static void main(String[] args) throws Exception
        String fileName = "D:\\\\Users\\\\admin\\\\Desktop\\\\140k_products.txt";
        List<Product> productList = file2List(fileName);
        System.out.println(productList.size());
    

    public static List<Product> file2List(String fileName) throws Exception
        File file = new File(fileName);
        List<String> list = FileUtils.readLines(file, "utf-8");
        List<Product> productList = new ArrayList<>();
        for(String str:list)
            String[] split = str.split(",");
            Product product = new Product(Integer.parseInt(split[0]),split[1],split[2],Float.parseFloat(split[3]),split[4],split[5]);
            productList.add(product);
        
        return productList;
    

1.4.2 批量新增

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;

import java.io.IOException;
import java.util.List;
import java.util.Map;

public class TestESBatch 

    private static RestHighLevelClient client
            = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
    private static String indexName = "test001";

    public static void main(String[] args) throws Exception
         //检查索引和创建索引在示例Demo中已经存在,因此不在进行重复展示
        if(!checkExistIndex(indexName))
            createIndex(indexName);
        
        // 14万数据
        String fileName = "D:\\\\Users\\\\admin\\\\Desktop\\\\140k_products.txt";
        List<Product> productList = ProductUtil.file2List(fileName);
        System.out.printf("准备数据 %d 条",productList.size());
        batchInsert(productList);

        client.close();
    

    private static void batchInsert(List<Product> productList) throws Exception
        BulkRequest request = new BulkRequest();
        for(Product pro:productList)
            Map o = (Map) JSONObject.toJSON(pro);
            //此处的 .id方法 指定了就是自定义id 否则是用 ES生成id
            IndexRequest indexRequest= new IndexRequest(indexName).id(pro.getId()+"").source(o);
            request.add(indexRequest);
        
        client.bulk(request,RequestOptions.DEFAULT);
        System.out.println("批量插入完成");
    

1.5 查询操作

import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.ScoreSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;

import java.io.IOException;

public class TestESQuery 

    private static RestHighLevelClient client
            = new RestHighLevelClient(RestClient.builder(new HttpHost("localhost", 9200, "http")));
    private static String indexName = "test002";

    public static void main(String[] args) throws Exception 
        String keyword = "时尚连衣裙";
        int start = 0;
        int count = 10;

        SearchHits hits = search(keyword, start, count);

        SearchHit[] searchHits = hits.getHits();
        for (SearchHit hit : searchHits) 
            System.out.println(hit.getId()+"----"+hit.getScore()+"===="+hit.getSourceAsString());
        
        client.close();
    

    private static SearchHits search(String keyword, int start, int count) throws IOException 
        SearchRequest searchRequest = new SearchRequest(indexName);

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //关键字匹配
        MatchQueryBuilder matchQueryBuilder = new MatchQueryBuilder("name",keyword );
        //模糊匹配
        matchQueryBuilder.fuzziness(Fuzziness.AUTO);
        sourceBuilder.query(matchQueryBuilder);
        sourceBuilder.from(start);//第几页
        sourceBuilder.size(count); //第几条
        //匹配 分值 度从高到低
        sourceBuilder.sort(SortBuilders.scoreSort().order(SortOrder.DESC));

//        sourceBuilder.sort(SortBuilders.fieldSort("price").order(SortOrder.ASC));
		//指定字段排序
        sourceBuilder.sort("price", SortOrder.DESC);

        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        SearchHits hits = searchResponse.getHits();
        return hits;
    


ElasticSearch 8 学习笔记总结

文章目录

一. ES8 的Java API 环境准备

ES8 废除了Type的概念。为了适应这种数据结构的改变,ES官方从1.7版本开始建议使用新的Elasticsearch Java Client。


搭建maven环境:

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

<dependencies>
    <dependency>
        <groupId>org.elasticsearch.plugin</groupId>
        <artifactId>x-pack-sql-jdbc</artifactId>
        <version>8.6.2</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>

获取客户端对象:

因为,服务注册的是基于https的安全elasticsearch服务认证,所以,将之前的证书进行一个转换:

# 生成es-api-ca.crt证书,之前没有密码设置。
openssl pkcs12 -in elastic-stack-ca.p12 -clcerts -nokeys -out es-api-ca.crt

将生成的证书放到项目里面。

创建连接对象:

package com.itholmes.elasticsearch.api;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
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.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;

public class ESClient 

    public static void main(String[] args) throws Exception
        // 初始化ES服务器的连接
        initESConnection();
    

    public static void initESConnection() throws Exception
        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 声明ES当前登录的账号密码
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials("elastic","3j=JYpywv=jMtQB+XIXS"));
        // 证书的路径
        Path caCertificatePath = Paths.get("E:\\\\itholmes\\\\demo\\\\itholmes-es8\\\\certs\\\\es-api-ca.crt");
        // x.509 , pkcs12都是 证书的算法
        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);
        SSLContext sslContext = sslContextBuilder.build();
        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.43.133", 9200, "https"))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() 
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) 
                        return httpClientBuilder.setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                                .setDefaultCredentialsProvider(credentialsProvider);
                    
                );

        // 创建客户端
        RestClient restClient = builder.build();
        // 通过客户端,创建传输对象
        RestClientTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        // 同步客户端对象
        ElasticsearchClient client = new ElasticsearchClient(transport);
        // 异步客户端对象
        ElasticsearchAsyncClient asyncClient = new ElasticsearchAsyncClient(transport);

        // fixme 同步是需要关闭的,而异步是不需要关闭的。
        transport.close();
    


二. ES8 的Java API 索引操作

ES Java的API相关操作:

  • 采用构造器形式来创建所需要的对象。
  • 通过lambda来创建。

对象形式操作:

package com.itholmes.elasticsearch.api;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.*;
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.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;

public class ESClient 

    private static ElasticsearchClient client;

    private static ElasticsearchAsyncClient asyncClient;

    private static ElasticsearchTransport transport;

    public static final String INDEX_HOLMES = "itholmes";

    public static void main(String[] args) throws Exception
        // 初始化ES服务器的连接
        initESConnection();
        // 操作索引
        operationIndex();
    
    // 操作索引
    private static void operationIndex() throws Exception
        // 获取索引客户端对象
        ElasticsearchIndicesClient indices = client.indices();
        // 判断索引是否存在
        ExistsRequest existsRequest = new ExistsRequest.Builder().index(INDEX_HOLMES).build();
        final boolean flg = indices.exists(existsRequest).value();
        if (flg)
            System.out.println("索引" + INDEX_HOLMES + "已经存在!");
         else 
            // 创建索引
            // CreateIndexRequest构造方法已经私有化了,所以需要采用构建器方式来构建对象。ES的API对象基本上都采用构建器的方式创建对象。
            CreateIndexRequest request = new CreateIndexRequest.Builder()
                    .index(INDEX_HOLMES)
                    .build();
            final CreateIndexResponse createIndexResponse = indices.create(request);
            System.out.println("创建索引的响应对象" + createIndexResponse);
        
        // 查询索引
        GetIndexRequest getIndexRequest = new GetIndexRequest.Builder().index(INDEX_HOLMES).build();
        final GetIndexResponse getIndexResponse = indices.get(getIndexRequest);
        // IndexState itholmes = getIndexResponse.get("itholmes");
        System.out.println("查询的响应结果:" + getIndexResponse);
        // 删除索引
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest.Builder().index(INDEX_HOLMES).build();
        DeleteIndexResponse delete = indices.delete(deleteIndexRequest);
        System.out.println("索引删除成功:" + delete);
        // fixme 同步是需要关闭的,而异步是不需要关闭的。
        transport.close();
    

    public static void initESConnection() throws Exception
        final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        // 声明ES当前登录的账号密码
        credentialsProvider.setCredentials(AuthScope.ANY,new UsernamePasswordCredentials("elastic","3j=JYpywv=jMtQB+XIXS"));
        // 证书的路径
        Path caCertificatePath = Paths.get("E:\\\\itholmes\\\\demo\\\\itholmes-es8\\\\certs\\\\es-api-ca.crt");
        // x.509 , pkcs12都是 证书的算法
        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);
        SSLContext sslContext = sslContextBuilder.build();
        RestClientBuilder builder = RestClient.builder(new HttpHost("192.168.43.133", 9200, "https"))
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() 
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) 
                        return httpClientBuilder.setSSLContext(sslContext).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                                .setDefaultCredentialsProvider(credentialsProvider);
                    
                );

        // 创建客户端
        RestClient restClient = builder.build();
        // 通过客户端,创建传输对象
        transport = new RestClientTransport(restClient, new JacksonJsonpMapper());

        // 同步客户端对象
        client = new ElasticsearchClient(transport);
        // 异步客户端对象
        asyncClient = new ElasticsearchAsyncClient(transport);
    


lambda方式创建索引:(推荐使用,代码简洁)

package com.itholmes.elasticsearch.api;

import co.elastic.clients.elasticsearch.ElasticsearchAsyncClient;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.indices.*;
import co.elastic.clients.json.jackson.JacksonJsonpMapper;
import co.elastic.clients.transport.ElasticsearchTransport;
import co.elastic.clients.transport.rest_client.RestClientTransport;
import co.elastic.clients.util.ObjectBuilder;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
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.ElasticSearch在JavaAPI中的操作(入门)

ElasticSearch高级操作

ElasticSearch JavaAPI(java操作)

JavaApi操作ElasticSearch(强烈推荐)

ElasticSearch聚合查询Restful语法和JavaApi详解(基于ES7.6)

ElasticSearch聚合查询Restful语法和JavaApi详解(基于ES7.6)