常用工具(十二) --ElasticSearchHelper

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.ElasticsearchGenerationException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.*;
import org.elasticsearch.action.bulk.BulkProcessor.Listener;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
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.core.CountRequest;
import org.elasticsearch.client.core.CountResponse;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.reindex.BulkByScrollResponse;
import org.elasticsearch.index.reindex.ScrollableHitSource;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.javatuples.Triplet;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

public class ESHelper {


    private Builder builder;
    private RestHighLevelClient highLevelClient;


    public ESHelper(List<HttpHost> hosts) {
        initial();
    }

    public ESHelper(Builder builder) {
        this.builder = builder;
        initial();
    }

    public void initial() {
        if (null != builder) {
            Map<String, Integer> hosts = builder.getHosts();
            String host = builder.getHost();
            int port = builder.getPort();
            if (null != hosts && hosts.size() > 0) {
                HttpHost[] httpHosts = new HttpHost[hosts.size()];
                int index = 0;
                for (Entry<String, Integer> hostEntry : hosts.entrySet()) {
                    httpHosts[index] = new HttpHost(hostEntry.getKey(), hostEntry.getValue());
                    index++;
                }
            } else {
                if (!StringUtils.isEmpty(host) && port > 0) {
                    highLevelClient = new RestHighLevelClient(RestClient.builder(new HttpHost(host, port)));
                } else {
                    throw new RuntimeException("无法初始化ES的highLevelClient!");
                }
            }
        } else {
            throw new RuntimeException("无法初始化ES的highLevelClient!");
        }
    }

    public static Builder builder() {
        return new Builder();
    }

    public static class Builder {
        private String driver = "org.elasticsearch.xpack.sql.jdbc.EsDriver";
        private String url = "jdbc:es://http://localhost:9200?timezone=UTC";
        private String host;
        private int port;
        private Map<String, Integer> hosts;
        private Properties prop = new Properties();

        protected String geDriver() {
            return driver;
        }

        public Builder withDriver(String driver) {
            this.driver = driver;
            return this;
        }

        protected String getUrl() {
            return url;
        }

        public Builder withUrl(String url) {
            this.url = url;
            return this;
        }

        protected String getHost() {
            return host;
        }

        public Builder withHost(String host) {
            this.host = host;
            return this;
        }

        protected int getPort() {
            return port;
        }

        public Builder withPort(int port) {
            this.port = port;
            return this;
        }

        protected Map<String, Integer> getHosts() {
            return hosts;
        }

        public Builder withHosts(Map<String, Integer> hosts) {
            this.hosts = hosts;
            return this;
        }

        public Properties getProp() {
            return prop;
        }

        public void withProp(Properties prop) {
            this.prop = prop;
        }

        public ESHelper build() {
            return new ESHelper(this);
        }
    }

    /**
     * 验证索引是否存在
     */
    public boolean existIndex(String indexName) {
        boolean status = false;
        GetIndexRequest request = new GetIndexRequest(indexName);
        try {
            status = highLevelClient.indices().exists(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        return status;
    }

    /**
     * 创建索引
     */
    public boolean createIndex(String indexName) {
        boolean status = false;
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        try {
            if (!existIndex(indexName)) {
                CreateIndexResponse response = highLevelClient.indices().create(request, RequestOptions.DEFAULT);
                if (response.isAcknowledged() || response.isShardsAcknowledged()) {
                    status = true;
                }
            } else {
                System.err.println("==== 索引[" + indexName + "]不存在! ====");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return status;
    }

    /**
     * 创建索引
     */
    public boolean asyncCreateIndex(String indexName) {
        boolean status = false;
        CreateIndexRequest request = new CreateIndexRequest(indexName);
        try {
            if (!existIndex(indexName)) {
                highLevelClient.indices().createAsync(request, RequestOptions.DEFAULT, new ActionListener<CreateIndexResponse>() {
                    @Override
                    public void onResponse(CreateIndexResponse response) {
                    }

                    @Override
                    public void onFailure(Exception e) {
                    }
                });
            } else {
                System.err.println("==== 索引[" + indexName + "]不存在! ====");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return status;
    }

    /**
     * 删除索引
     */
    public boolean deleteIndex(String indexName) {
        boolean status = false;
        DeleteIndexRequest request = new DeleteIndexRequest(indexName);
        try {
            if (existIndex(indexName)) {
                highLevelClient.indices().delete(request, RequestOptions.DEFAULT);
            } else {
                System.err.println("==== 索引[" + indexName + "]不存在! ====");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return status;
    }

    public void close() {
        try {
            if (null != highLevelClient) {
                highLevelClient.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 批量处理数据
     */
    public BulkResponse bulkDocument(List<DocWriteRequest<?>> requests) throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        requests.forEach(req -> {
            bulkRequest.add(req);
        });
        return highLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    }


    public void indexDocument(IndexRequest indexRequest) throws IOException {
        highLevelClient.index(indexRequest, RequestOptions.DEFAULT);
    }

    /**
     * 异步批量数据处理
     */
    public void bulkAsyncDocument(List<DocWriteRequest<?>> requests) {
        bulkAsyncListenerDocument(requests, actionListener());
    }

    /**
     * 异步批量数据处理-自定义响应
     */
    public void bulkAsyncListenerDocument(List<DocWriteRequest<?>> requests, ActionListener<BulkResponse> actionListener) {
        BulkRequest bulkRequest = new BulkRequest();
        requests.forEach(req -> {
            bulkRequest.add(req);
        });
        highLevelClient.bulkAsync(bulkRequest, RequestOptions.DEFAULT, actionListener);
    }


    private ActionListener<BulkResponse> actionListener() {
        ActionListener<BulkResponse> listener = new ActionListener<BulkResponse>() {
            @Override
            public void onResponse(BulkResponse bulkResponse) {
                if (bulkResponse.hasFailures()) {
                    System.err.println("Increased resource failure causes:" + bulkResponse.buildFailureMessage());
                }
            }

            @Override
            public void onFailure(Exception e) {
                System.err.println("Asynchronous batch increases data exceptions:" + e.getLocalizedMessage());
            }
        };
        return listener;
    }


    /**
     * 检索
     */
    public SearchResult searchDocument(SearchRequest searchRequest) {
        List<Map<String, Object>> list = new ArrayList<>();
        SearchResponse searchResponse;
        try {
            searchResponse = highLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            SearchHit[] searchHit = searchResponse.getHits().getHits();
            searchResponse.getTook().getMillis();
            long totalHits = searchResponse.getHits().getTotalHits().value;
            long took = searchResponse.getTook().getMillis();
            for (SearchHit document : searchHit) {
                Map<String, Object> item = document.getSourceAsMap();
                if (item == null) {
                    continue;
                }
                Map<String, HighlightField> highlightFields = document.getHighlightFields();
                if (!highlightFields.isEmpty()) {
                    for (String key : highlightFields.keySet()) {
                        Text[] fragments = highlightFields.get(key).fragments();
                        if (item.containsKey(key)) {
                            item.put(key, fragments[0].string());
                        }
                        String[] fieldArray = key.split("[.]");
                        if (fieldArray.length > 1) {
                            item.put(fieldArray[0], fragments[0].string());
                        }
                    }
                }
                list.add(item);
            }
            Map<String, Map<String, Long>> aggregations = getAggregation(searchResponse.getAggregations());
            return new SearchResult(totalHits, list, took, aggregations);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new SearchResult();
    }


    private Map<String, Map<String, Long>> getAggregation(Aggregations aggregations) {
        if (aggregations == null) {
            return Collections.EMPTY_MAP;
        }
        Map<String, Map<String, Long>> result = new HashMap<>();
        Map<String, Aggregation> aggregationMap = aggregations.getAsMap();
        aggregationMap.forEach((k, v) -> {
            Map<String, Long> agg = new HashMap<>();
            List<? extends Terms.Bucket> buckets = ((ParsedStringTerms) v).getBuckets();
            for (Terms.Bucket bucket : buckets) {
                agg.put(bucket.getKeyAsString(), bucket.getDocCount());
            }
            result.put(k, agg);
        });
        return result;
    }

    /**
     * Bulk监听器
     */
    private static Listener getBulkListener() {
        Listener listener = new Listener() {
            @Override
            public void beforeBulk(long executionId, BulkRequest request) {
            }

            @Override
            public void afterBulk(long executionId, BulkRequest request, BulkResponse response) {
            }

            @Override
            public void afterBulk(long executionId, BulkRequest request, Throwable failure) {
            }
        };
        return listener;
    }

    /**
     * 保存index,将传入Object类型的JavaBean解析成List<Triplet<String, String, Object>>(fieldName, fieldType, fieldValue)
     * 默认使用id作为ElasticSearch中index的id,不使用ES的随机ID
     */
    public void save(Object obj) {
        try {
            List<Triplet<String, String, Object>> triplets = ReflectUtil.objToTriplet(obj, false);
            save(1, triplets, "id");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存index,将传入Object类型的JavaBean解析成List<Triplet<String, String, Object>>(fieldName, fieldType, fieldValue)
     *
     * @param obj JavaBean实例
     * @param id  ES中index的id
     */
    public void save(Object obj, String id) {
        try {
            List<Triplet<String, String, Object>> triplets = ReflectUtil.objToTriplet(obj, false);
            save(1, triplets, id);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存index
     *
     * @param triplets 三元组类型Triplet<String, String, Object>(fieldName, fieldType, fieldValue)
     * @param id       ES中index的id,不使用ES的随机ID
     */
    public void save(int bulkNumber, List<Triplet<String, String, Object>> triplets, String id) {
        Listener listener = getBulkListener();
        BulkProcessor bulkProcessor = BulkProcessor.builder(
                (request, bulkListener) -> highLevelClient.bulkAsync(request, RequestOptions.DEFAULT, bulkListener), listener).build();
        try {
            BulkProcessor.Builder builder = BulkProcessor.builder(
                    (request, bulkListener) -> highLevelClient.bulkAsync(request, RequestOptions.DEFAULT, bulkListener), listener);
            builder.setBulkActions(bulkNumber);
            builder.setBulkSize(new ByteSizeValue(1L, ByteSizeUnit.MB));
            builder.setConcurrentRequests(0);
            builder.setFlushInterval(TimeValue.timeValueSeconds(10L));
            builder.setBackoffPolicy(BackoffPolicy.constantBackoff(TimeValue.timeValueSeconds(1L), 3));
            Map<String, String> source = new HashMap<String, String>();
            triplets.forEach(tpl -> {
                source.put(tpl.getValue0(), tpl.getValue2().toString());
            });
            String docId = source.get(id);
            IndexRequest request = new IndexRequest(docId);
            request.id(docId);
            request.source(source);
            bulkProcessor.add(request);
        } catch (ElasticsearchGenerationException e) {
            e.printStackTrace();
        } finally {
            bulkProcessor.close();
        }
    }

    /**
     * 删除
     */
    public Boolean deleteDocument(DeleteRequest request) throws IOException {
        DeleteResponse deleteResponse = highLevelClient.delete(request, RequestOptions.DEFAULT);
        if (deleteResponse.getResult() == DocWriteResponse.Result.NOT_FOUND) {
            System.out.println("not found doc id: " + deleteResponse.getId());
            return false;
        }
        if (deleteResponse.getResult() == DocWriteResponse.Result.DELETED) {
            return true;
        }
        System.out.println("deleteResponse Status: " + deleteResponse.status());
        return false;
    }


    /**
     * 异步查询更新
     */
    public void updateByQueryDocument(UpdateByQueryRequest request) {
        try {
            highLevelClient.updateByQuery(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private ActionListener<BulkByScrollResponse> bulkByScrolllistener() {
        return new ActionListener<BulkByScrollResponse>() {
            @Override
            public void onResponse(BulkByScrollResponse bulkResponse) {
                List<BulkItemResponse.Failure> failures = bulkResponse.getBulkFailures();
                if (!failures.isEmpty()) {
                    System.err.println("BulkByScrollResponse failures: " + StringUtils.join(failures, "@"));
                }
                List<ScrollableHitSource.SearchFailure> searchFailures = bulkResponse.getSearchFailures();
                if (!failures.isEmpty()) {
                    System.err.println("BulkByScrollResponse searchFailures: " + StringUtils.join(searchFailures, "@@"));
                }
            }

            @Override
            public void onFailure(Exception e) {
                System.err.println("BulkByScrollResponse Exceptions:" + e.getLocalizedMessage());
            }
        };
    }

    /**
     * 个数查询
     */
    public Long countDocument(CountRequest countRequest) {
        try {
            CountResponse countResponse = highLevelClient.count(countRequest, RequestOptions.DEFAULT);
            return countResponse.getCount();
        } catch (IOException e) {
            System.err.println("CountResponse Exceptions:" + e.getLocalizedMessage());
            return 0L;
        }
    }

    public boolean updateDocument(UpdateRequest updateRequest) {
        try {
            highLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public void lambdaUpdateDocument(String index, String docId, Map<?, ?> fields) throws IOException {
        UpdateRequest request = new UpdateRequest(index, docId);
        request.doc(fields);
        highLevelClient.update(request, RequestOptions.DEFAULT);
    }

    public class SearchResult {
        /**
         * 命中总数
         **/
        public Long totalHits;
        /**
         * 返回文档集合
         **/
        public List<Map<String, Object>> documents;

        /**
         * 查询耗时 单位毫秒
         **/
        public Long took;
        /**
         * 聚合结果
         **/
        public Map<String, Map<String, Long>> aggregations;

        public SearchResult(Long totalHits,
                            List<Map<String, Object>> documents,
                            Long took,
                            Map<String, Map<String, Long>> aggregations) {
            this.totalHits = totalHits;
            this.documents = documents;
            this.took = took;
            this.aggregations = aggregations;
        }

        public SearchResult() {
            this.totalHits = 0L;
            this.documents = new ArrayList<>();
            this.took = 0L;
        }
    }

    public static void main(String[] args) {
        ESHelper helper = ESHelper.builder().withHost("localhost").withPort(9200).build();
        String indexName = "onefun";
         System.out.println(helper.createIndex(indexName));
         System.out.println(helper.existIndex(indexName));
        helper.close();
    }

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
public void testSimpleImportBuilder(){ DB2ESImportBuilder importBuilder = DB2ESImportBuilder.newInstance(); try { //清除测试表数据 ElasticSearchHelper.getRestClientUtil().dropIndice("dbclobdemo"); } catch (Exception e){ } //数据源相关配置,可选项,可以在外部启动数据源 importBuilder.setDbName("test") .setDbDriver("com.mysql.jdbc.Driver") //数据库驱动程序,必须导入相关数据库的驱动jar包 .setDbUrl("jdbc:mysql://localhost:3306/bboss?useCursorFetch=true") //通过useCursorFetch=true启用mysql的游标fetch机制,否则会有严重的性能隐患,useCursorFetch必须和jdbcFetchSize参数配合使用,否则不会生效 .setDbUser("root") .setDbPassword("123456") .setValidateSQL("select 1") .setUsePool(false);//是否使用连接池 //指定导入数据的sql语句,必填项,可以设置自己的提取逻辑 importBuilder.setSql("select * from td_cms_document"); /** * es相关配置 */ importBuilder .setIndex("dbclobdemo") //必填项 .setIndexType("dbclobdemo") //必填项 .setRefreshOption(null)//可选项,null表示不实时刷新,importBuilder.setRefreshOption("refresh");表示实时刷新 .setUseJavaName(true) //可选项,将数据库字段名称转换为java驼峰规范的名称,例如:doc_id -> docId .setBatchSize(5000) //可选项,批量导入es的记录数,默认为-1,逐条处理,> 0时批量处理 .setJdbcFetchSize(10000);//设置数据库的查询fetchsize,同时在mysql url上设置useCursorFetch=true启用mysql的游标fetch机制,否则会有严重的性能隐患,jdbcFetchSize必须和useCursorFetch参数配合使用,否则不会生效 /** * 执行数据库表数据导入es操作 */ DataStream dataStream = importBuilder.builder(); dataStream.execute(); }
07-23

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值