All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fun.langel.cql.datasource.support.ElasticSearchDataSource Maven / Gradle / Ivy

The newest version!
package fun.langel.cql.datasource.support;


import fun.langel.cql.Cql;
import fun.langel.cql.Language;
import fun.langel.cql.constant.Const;
import fun.langel.cql.datasource.*;
import fun.langel.cql.dialect.Dialect;
import fun.langel.cql.resolve.DialectResolver;
import fun.langel.cql.resolve.RvResolver;
import fun.langel.cql.resolve.dialect.ElasticSearchQDLDialectResolver;
import fun.langel.cql.resolve.rv.ElasticSearchRvResolver;
import fun.langel.cql.rv.ReturnValue;
import fun.langel.cql.statement.SelectStatement;
import fun.langel.cql.util.Props;
import fun.langel.cql.util.StringUtil;
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.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
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.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.Properties;

/**
 * @author [email protected](GuHan)
 * @since 2022/3/18 17:07
 **/
public class ElasticSearchDataSource implements DataSource {

    private Connection connection;

    @Override
    public DataSourceType type() {
        return DataSourceType.ELASTIC_SEARCH;
    }

    @Override
    public Connection getConnection() {
        Properties props = new Properties();
        String host = StringUtil.isEmpty(Props.getProperty(Const.CAVE_ELASTICSEARCH_HOST)) ?
                Props.getProperty(Const.ES_HOST) : Props.getProperty(Const.CAVE_ELASTICSEARCH_HOST);
        props.setProperty(Const.CAVE_ELASTICSEARCH_HOST, host);
        String username = StringUtil.isEmpty(Props.getProperty(Const.CAVE_ELASTICSEARCH_USERNAME)) ?
                Props.getProperty(Const.ES_USERNAME) : Props.getProperty(Const.CAVE_ELASTICSEARCH_USERNAME);

        props.setProperty(Const.CAVE_ELASTICSEARCH_USERNAME, username == null ? "" : username);
        String password = StringUtil.isEmpty(Props.getProperty(Const.CAVE_ELASTICSEARCH_PASSWORD)) ?
                Props.getProperty(Const.ES_PASSWORD) : Props.getProperty(Const.CAVE_ELASTICSEARCH_PASSWORD);
        props.setProperty(Const.CAVE_ELASTICSEARCH_PASSWORD, password == null ? "" : password);
        if (this.connection == null) {
            synchronized (ElasticSearchDataSource.class) {
                if (this.connection == null) {
                    this.connection = createConnection(props);
                }
            }
        }
        return this.connection;
    }

    public Connection createConnection(Properties props) {
        return new ElasticSearchConnection(props);
    }

}

class ElasticSearchConnection implements Connection {

    private final Properties props;

    private HttpHost[] hosts = null;

    private RestHighLevelClient restClient;

    public ElasticSearchConnection(Properties props) {
        this.props = props;
        prepareArguments();
        prepareConnect();
    }

    private void prepareArguments() {
        String pHosts = this.props.getProperty(Const.CAVE_ELASTICSEARCH_HOST);


        String[] hostArray = pHosts.split(",");
        final HttpHost[] hosts = new HttpHost[hostArray.length];

        for (int idx = 0, len = hostArray.length; idx < len; idx++) {
            StringBuilder host = new StringBuilder(hostArray[idx]);
            if (host.indexOf(":") < 0) {
                host.append(":9200");
            }
            hosts[idx] = HttpHost.create(host.toString());
        }
        this.hosts = hosts;
    }

    private void prepareConnect() {
        // Create the low-level client
        // RestClient httpClient = RestClient.builder(this.hosts).build();

// Create the HLRC
//         this.restClient = new RestHighLevelClientBuilder(httpClient)
//                 .setApiCompatibilityMode(true)
//                 .build();
        String username = this.props.getProperty(Const.CAVE_ELASTICSEARCH_USERNAME);
        String password = this.props.getProperty(Const.CAVE_ELASTICSEARCH_PASSWORD);
        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        if (!StringUtil.isEmpty(username) && !StringUtil.isEmpty(password)) {
            credentialsProvider.setCredentials(AuthScope.ANY,
                    new UsernamePasswordCredentials(username, password));
        }

        this.restClient = new RestHighLevelClient(RestClient.builder(this.hosts)
                .setHttpClientConfigCallback(new RestClientBuilder.HttpClientConfigCallback() {
                    @Override
                    public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpAsyncClientBuilder) {
                        httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
                        //线程设置
                        // httpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(10).build());
                        return httpAsyncClientBuilder;
                    }
                }));

    }

    @Override
    public Session getSession() {
        return new ElasticSearchSession(this.props, this.restClient);
    }
}

class ElasticSearchSession extends PreparedSession {

    private static final Logger LOG = LoggerFactory.getLogger(ElasticSearchSession.class);

    private final RestHighLevelClient restClient;

    private final Properties props;

    private final DialectResolver dialectResolver;

    private final RvResolver rvResolver;

    public ElasticSearchSession(final Properties props, final RestHighLevelClient restClient) {
        this.props = props;
        this.restClient = restClient;
        this.dialectResolver = new ElasticSearchQDLDialectResolver();
        this.rvResolver = new ElasticSearchRvResolver();
    }

    @Override
    public Language lang() {
        return Language.ELASTIC_SEARCH;
    }

    @Override
    public ReturnValue executeQuery0(String sql) {
        SelectStatement select = Cql.parseSelectStatement(sql);
        Dialect dialect = this.dialectResolver.resolve(select);
        try {
            SearchResponse esResp = this.restClient.search(dialect.content(), RequestOptions.DEFAULT);
            return this.rvResolver.resolve(esResp, select.columns());
        } catch (IOException e) {
            LOG.error(e.getMessage(), e);
        }
        return null;
    }

    @Override
    public Number executeUpdate0(String sql) {
        return null;
    }

    @Override
    public Number executeDelete0(String sql) {
        return null;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy