SpringBoot+RestHighLevelClient调用ElasticSearch。

16 篇文章 0 订阅
15 篇文章 0 订阅

JavaREST客户端有两种模式: Java低级REST客户端和高级REST客户端。低级别的客户端通过http与Elasticearch集群通信,版本兼容性好。高级REST客户端是基于低级客户端API的封装,版本兼容性差。需要的Java1.8以上的版本。Elasticsearch需要6.0以上。

Maven依赖

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

配置文件

ElasticSearch的配置信息如下,包括ElasticSearch服务器地址、端口号、索引名字、类型名字。我这里用的是application.yml

server:
  port: 8080

spring:
  application:
    name: springboot-elasticsearch-example

elasticsearch:
  schema: http
  address: 120.48.54.67:9002
  connectTimeout: 10000
  socketTimeout: 10000
  connectionRequestTimeout: 10000
  maxConnectNum: 100
  maxConnectPerRoute: 100

初始化ElasticSearchConfig对象

配置文件写好后,使用使用一个ElasticSearchConfig实例化创建一个RestHighLevelClient的Bean实例,使用注解将配置文件的值注入到类中,创建RestHighLevelClient对象时可以看到,内部其实是创建了一个低级的客户端RestClient来实现,传入ElasticSearch的服务器地址和端口号。

package club.mydlq.elasticsearch.config;

import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.ArrayList;
import java.util.List;

/**
 * ElasticSearch 配置
 */
@Configuration
public class ElasticSearchConfig {

    /** 协议 */
    @Value("${elasticsearch.schema:http}")
    private String schema;

    /** 集群地址,如果有多个用“,”隔开 */
    @Value("${elasticsearch.address}")
    private String address;

    /** 连接超时时间 */
    @Value("${elasticsearch.connectTimeout:5000}")
    private int connectTimeout;

    /** Socket 连接超时时间 */
    @Value("${elasticsearch.socketTimeout:10000}")
    private int socketTimeout;

    /** 获取连接的超时时间 */
    @Value("${elasticsearch.connectionRequestTimeout:5000}")
    private int connectionRequestTimeout;

    /** 最大连接数 */
    @Value("${elasticsearch.maxConnectNum:100}")
    private int maxConnectNum;

    /** 最大路由连接数 */
    @Value("${elasticsearch.maxConnectPerRoute:100}")
    private int maxConnectPerRoute;

    @Bean
    public RestHighLevelClient restHighLevelClient() {
        // 拆分地址
        List<HttpHost> hostLists = new ArrayList<>();
        String[] hostList = address.split(",");
        for (String addr : hostList) {
            String host = addr.split(":")[0];
            String port = addr.split(":")[1];
            hostLists.add(new HttpHost(host, Integer.parseInt(port), schema));
        }
        // 转换成 HttpHost 数组
        HttpHost[] httpHost = hostLists.toArray(new HttpHost[]{});
        // 构建连接对象
        RestClientBuilder builder = RestClient.builder(httpHost);
        // 异步连接延时配置
        builder.setRequestConfigCallback(requestConfigBuilder -> {
            requestConfigBuilder.setConnectTimeout(connectTimeout);
            requestConfigBuilder.setSocketTimeout(socketTimeout);
            requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeout);
            return requestConfigBuilder;
        });
        // 异步连接数配置
        builder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setMaxConnTotal(maxConnectNum);
            httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
            return httpClientBuilder;
        });
        return new RestHighLevelClient(builder);
    }

}

客户端API使用

索引的增删改查:

package club.mydlq.elasticsearch.service.base;

import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.admin.indices.get.GetIndexRequest;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;

/**
 * 索引操作
 */
@Slf4j
@Service
public class IndexService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * 验证索引是否存在
     */
    public Object existsIndex() {
        Object result = "";
        try {
            // 获取索引请求
            GetIndexRequest request = new GetIndexRequest();
            // 设置要查询的索引名称
            request.indices("mydlq-user");
            // 执行请求,验证索引是否存在
            boolean isExist = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
            log.info("是否存在:{}", isExist);
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = isExist;
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

    /**
     * 创建索引
     */
    public Object createIndex() {
        Object result = "";
        try {
            // 创建 Mapping
            XContentBuilder mapping = XContentFactory.jsonBuilder()
                .startObject()
                    .field("dynamic", true)
                    .startObject("properties")
                        .startObject("name")
                            .field("type","text")
                            .startObject("fields")
                                .startObject("keyword")
                                    .field("type","keyword")
                                .endObject()
                            .endObject()
                        .endObject()
                        .startObject("address")
                            .field("type","text")
                            .startObject("fields")
                                .startObject("keyword")
                                    .field("type","keyword")
                                .endObject()
                            .endObject()
                        .endObject()
                        .startObject("remark")
                            .field("type","text")
                            .startObject("fields")
                                .startObject("keyword")
                                    .field("type","keyword")
                                .endObject()
                            .endObject()
                        .endObject()
                        .startObject("age")
                            .field("type","integer")
                        .endObject()
                        .startObject("salary")
                            .field("type","float")
                        .endObject()
                        .startObject("birthDate")
                            .field("type","date")
                            .field("format", "yyyy-MM-dd")
                        .endObject()
                        .startObject("createTime")
                            .field("type","date")
                        .endObject()
                    .endObject()
                .endObject();
            // 创建索引配置信息,配置
            Settings settings = Settings.builder()
                    .put("index.number_of_shards", 1)
                    .put("index.number_of_replicas", 0)
                    .build();
            // 新建创建索引请求对象,然后设置索引类型(ES 7.0 将不存在索引类型)和 mapping 与 index 配置
            CreateIndexRequest request = new CreateIndexRequest("mydlq-user", settings);
            request.mapping("doc", mapping);
            // RestHighLevelClient 执行创建索引
            CreateIndexResponse createIndexResponse = restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
            // 判断是否创建成功
            boolean isCreated = createIndexResponse.isAcknowledged();
            log.info("是否创建成功:{}", isCreated);
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = isCreated;
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

    /**
     * 删除索引
     */
    public Object deleteIndex() {
        Object result = "";
        try {
            // 新建删除索引请求对象
            DeleteIndexRequest request = new DeleteIndexRequest("mydlq-user");
            // 执行删除索引
            AcknowledgedResponse acknowledgedResponse = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
            // 判断是否删除成功
            boolean siDeleted = acknowledgedResponse.isAcknowledged();
            log.info("是否删除成功:{}", siDeleted);
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = siDeleted;
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

}

文档增删改查:

package club.mydlq.elasticsearch.service.base;

import club.mydlq.elasticsearch.model.entity.UserInfo;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
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 org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.Date;

/**
 * 文档操作
 */
@Slf4j
@Service
public class DocumentService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    public Object existsDocument() {
        Object result = "";
        try {
            // 获取请求对象
            GetRequest getRequest = new GetRequest("mydlq-user", "doc", "1");
            // 是否获取源码内容
            getRequest.fetchSourceContext(new FetchSourceContext(false));
            // 执行请求,验证文档是否存在
            boolean isExist = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
            log.info("文档是否存在:{}", isExist);
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = isExist;
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

    public Object getDocument() {
        Object result = "";
        try {
            // 获取请求对象
            GetRequest getRequest = new GetRequest("mydlq-user", "doc", "1");
            // 获取文档信息
            GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
            // 将 JSON 转换成对象
            if (getResponse.isExists()) {
                UserInfo userInfo = JSON.parseObject(getResponse.getSourceAsBytes(), UserInfo.class);
                log.info("用户信息:{}", userInfo);
            }
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = getResponse.getSourceAsString();
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

    public Object addDocument() {
        Object result = "";
        try {
            // 创建索引请求对象
            IndexRequest indexRequest = new IndexRequest("mydlq-user", "doc", "1");
            // 创建用户信息
            UserInfo userInfo = new UserInfo();
            userInfo.setName("张三");
            userInfo.setAge(29);
            userInfo.setSalary(100.00f);
            userInfo.setAddress("北京市");
            userInfo.setRemark("来自北京市的张先生");
            userInfo.setCreateTime(new Date());
            userInfo.setBirthDate("1990-01-10");
            // 将对象转换为 byte 数组
            byte[] json = JSON.toJSONBytes(userInfo);
            // 设置文档内容
            indexRequest.source(json, XContentType.JSON);
            // 执行增加文档
            IndexResponse response = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
            log.info("创建状态:{}", response.status());
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = response.getResult();
        } catch (Exception e) {
            log.error("", e);
        }
        return result;
    }

    public Object updateDocument() {
        Object result = "";
        try {
            // 创建索引请求对象
            UpdateRequest updateRequest = new UpdateRequest("mydlq-user", "doc", "1");
            // 设置用户更新信息
            UserInfo userInfo = new UserInfo();
            userInfo.setSalary(200.00f);
            userInfo.setAddress("北京市海淀区");
            // 将对象转换为 byte 数组
            byte[] json = JSON.toJSONBytes(userInfo);
            // 设置更新文档内容
            updateRequest.doc(json, XContentType.JSON);
            // 执行更新文档
            UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
            log.info("创建状态:{}", response.status());
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = response.getResult();
        } catch (Exception e) {
            log.error("", e);
        }
        return result;
    }

    public Object deleteDocument() {
        Object result = "";
        try {
            // 创建删除请求对象
            DeleteRequest deleteRequest = new DeleteRequest("mydlq-user", "doc", "1");
            // 执行删除文档
            DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            log.info("删除状态:{}", response.status());
            // 根据具体业务逻辑返回不同结果,这里为了方便直接将结果返回
            result = response.getResult();
        } catch (IOException e) {
            log.error("", e);
        }
        return result;
    }

}

聚合查询

package club.mydlq.elasticsearch.service.aggregation;

import lombok.extern.slf4j.Slf4j;
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.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.metrics.tophits.ParsedTopHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.List;

/**
 * 聚合 Bucket 与 Metric
 */
@Slf4j
@Service
public class AggrBucketMetricService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    /**
     * topHits 按照员工岁数分桶、然后统计每个岁数员工工资最高值
     */
    public Object aggregationTopHits() {
        String responseResult = "";
        try {
            AggregationBuilder testTop = AggregationBuilders.topHits("salary_max_user")
                    .size(1)
                    .sort("salary", SortOrder.DESC);
            AggregationBuilder salaryBucket = AggregationBuilders.terms("salary_bucket")
                    .field("age")
                    .size(10);
            salaryBucket.subAggregation(testTop);
            // 查询源构建器
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            searchSourceBuilder.size(0);
            searchSourceBuilder.aggregation(salaryBucket);
            // 创建查询请求对象,将查询条件配置到其中
            SearchRequest request = new SearchRequest("mydlq-user");
            request.source(searchSourceBuilder);
            // 执行请求
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            // 获取响应中的聚合信息
            Aggregations aggregations = response.getAggregations();
            // 输出内容
            if (RestStatus.OK.equals(response.status())) {
                // 分桶
                Terms byCompanyAggregation = aggregations.get("salary_bucket");
                List<? extends Terms.Bucket> buckets = byCompanyAggregation.getBuckets();
                // 输出各个桶的内容
                log.info("-------------------------------------------");
                log.info("聚合信息:");
                for (Terms.Bucket bucket : buckets) {
                    log.info("桶名:{}", bucket.getKeyAsString());
                    ParsedTopHits topHits = bucket.getAggregations().get("salary_max_user");
                    for (SearchHit hit:topHits.getHits()){
                        log.info(hit.getSourceAsString());
                    }
                }
                log.info("-------------------------------------------");
                // 根据具体业务逻辑返回不同结果,这里为了方便直接将返回响应对象Json串
                responseResult = response.toString();
            }
        } catch (IOException e) {
            log.error("", e);
        }
        return responseResult;
    }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值