zoukankan      html  css  js  c++  java
  • ElasticSearch使用RestHighLevelClient进行搜索查询

    Elasticsearch Java API有四类client连接方式:TransportClient、  RestClient 、Jest、 Spring_Data_Elasticsearch。其中TransportClient、  RestClient是Elasticsearch原生的api,TransportClient会在8.0版本中完成删除,替代的是HighLevelRestClient,它使用HTTP请求而不是Java序列化请求。Spring_Data_Elasticsearch是spring集成的Elasticsearch开发包。在博客园 Elasticsearch 6.4基本操作 - Java版 一文中有简单的描述,不再过多引述。本文主要记录一下HighLevelRestClient在spingboot项目中的使用。

    使用es主要是做一些非关系型数据文档的检索,公司用的最多的是配合kibana进行可视化的日志检索,非常方便。elasticsearch、kibana安装,配置和使用,有大量博客记录,此处不再说明。

     @Configuration配置sping并启动容器 @Bean注册Bean

    import org.apache.http.HttpHost;
    import org.apache.http.client.config.RequestConfig.Builder;
    import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestClientBuilder;
    import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
    import org.elasticsearch.client.RestClientBuilder.RequestConfigCallback;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
     
    import java.util.ArrayList;
     
    @Configuration
    public class ESConfig {
     
        private static String hosts = "127.0.0.1"; // 集群地址,多个用,隔开
        private static int port = 9200; // 使用的端口号
        private static String schema = "http"; // 使用的协议
        private static ArrayList<HttpHost> hostList = null;
     
        private static int connectTimeOut = 1000; // 连接超时时间
        private static int socketTimeOut = 30000; // 连接超时时间
        private static int connectionRequestTimeOut = 500; // 获取连接的超时时间
     
        private static int maxConnectNum = 100; // 最大连接数
        private static int maxConnectPerRoute = 100; // 最大路由连接数
        static {
            hostList = new ArrayList<>();
            String[] hostStrs = hosts.split(",");
            for (String host : hostStrs) {
                hostList.add(new HttpHost(host, port, schema));
            }
        }
        @Bean
        public RestHighLevelClient client(){
            RestClientBuilder builder = RestClient.builder(hostList.toArray(new HttpHost[0]));
            // 异步httpclient连接延时配置
            builder.setRequestConfigCallback(new RequestConfigCallback() {
                @Override
                public Builder customizeRequestConfig(Builder requestConfigBuilder) {
                    requestConfigBuilder.setConnectTimeout(connectTimeOut);
                    requestConfigBuilder.setSocketTimeout(socketTimeOut);
                    requestConfigBuilder.setConnectionRequestTimeout(connectionRequestTimeOut);
                    return requestConfigBuilder;
                }
            });
            // 异步httpclient连接数配置
            builder.setHttpClientConfigCallback(new HttpClientConfigCallback() {
                @Override
                public HttpAsyncClientBuilder customizeHttpClient(HttpAsyncClientBuilder httpClientBuilder) {
                    httpClientBuilder.setMaxConnTotal(maxConnectNum);
                    httpClientBuilder.setMaxConnPerRoute(maxConnectPerRoute);
                    return httpClientBuilder;
                }
            });
            RestHighLevelClient client = new RestHighLevelClient(builder);
            return client;
        }
    }

    写一个service。

    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.index.query.BoolQueryBuilder;
    import org.elasticsearch.index.query.MatchQueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.index.query.RangeQueryBuilder;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.SearchHits;
    import org.elasticsearch.search.builder.SearchSourceBuilder;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
     
    import java.io.IOException;
    import java.util.Arrays;
     
    @Service
    public class ElasticSearchService {
        private static final Logger log = LoggerFactory.getLogger(ElasticSearchService.class);
     
        @Autowired
        private RestHighLevelClient client;
     
        public String search() throws IOException {
            BoolQueryBuilder boolBuilder = QueryBuilders.boolQuery();
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("fields.entity_id", "319");//这里可以根据字段进行搜索,must表示符合条件的,相反的mustnot表示不符合条件的
           // RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("fields_timestamp"); //新建range条件
           // rangeQueryBuilder.gte("2019-03-21T08:24:37.873Z"); //开始时间
           // rangeQueryBuilder.lte("2019-03-21T08:24:37.873Z"); //结束时间
           // boolBuilder.must(rangeQueryBuilder);
            boolBuilder.must(matchQueryBuilder);
            sourceBuilder.query(boolBuilder); //设置查询,可以是任何类型的QueryBuilder。
            sourceBuilder.from(0); //设置确定结果要从哪个索引开始搜索的from选项,默认为0
            sourceBuilder.size(100); //设置确定搜素命中返回数的size选项,默认为10
          sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS)); //设置一个可选的超时,控制允许搜索的时间。
    
    
            sourceBuilder.fetchSource(new String[] {"fields.port","fields.entity_id","fields.message"}, new String[] {}); //第一个是获取字段,第二个是过滤的字段,默认获取全部
            SearchRequest searchRequest = new SearchRequest("customer"); //索引
            searchRequest.types("doc"); //类型
            searchRequest.source(sourceBuilder);
            SearchResponse response = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = response.getHits();  //SearchHits提供有关所有匹配的全局信息,例如总命中数或最高分数:
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit hit : searchHits) {
                log.info("search -> {}",hit.getSourceAsString());
            }
            return Arrays.toString(searchHits);
        }
    }


    上面的ElasticSearchService 有几个常用的Builder类和方法需要了解下。

    BoolQueryBuilder 用来拼装查询条件。一般来说must的性能要低一些,因为他要进行打分评估,也就是说要进行_score,而filter则不会。 

    filter(QueryBuilder queryBuilder)

    Adds a query that must appear in the matching documents but will not contribute to scoring.
     
    must(QueryBuilder queryBuilder)
    Adds a query that must appear in the matching documents and will contribute to scoring.
     
    should(QueryBuilder queryBuilder)
    Adds a query that should appear in the matching documents.
     
    简单来说:must 相当于 与 & = ;must not 相当于 非 ~   !=;should 相当于 或  |   or ;filter  过滤
    //filter 效率比 must高的多 
     if (StringUtils.isNotBlank(query.getRouterDatabaseNo())) {
       boolQueryBuilder.filter(QueryBuilders.termQuery("routerDatabaseNo", query.getRouterDatabaseNo()));
     }
    
    //时间段 一定要有头有尾 不然会出现慢查询
     if (null != query.getCreateTime() && null != query.getUpdateTime()) {
         boolQueryBuilder.filter(QueryBuilders.rangeQuery("createTime").from( query.getCreateTime()).to(query.getUpdateTime()));
     }

    SearchSourceBuilder

     SearchRequest searchRequest = new SearchRequest("customer"); //将请求限制为一个索引
     SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
     searchRequest.types("doc"); //将请求限制为一个类型。
     searchRequest.source(sourceBuilder); //将SearchSourceBuilder添加到SeachRequest

    创建SeachRequest,没有参数,这将针对所有索引运行。有参数,则按参数所传值为索引,此处“customer”为索引值。大多数搜索参数都添加到SearchSourceBuilder中,它为搜索请求body中的所有内容提供了setter。

    SearchSourceBuilder的排序:允许添加一个或多个SortBuilder实例,有四种特殊的实现(Field-,Score-,GeoDistance-和ScriptSortBuilder)。

    sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC)); //按_score降序排序(默认值)。
    sourceBuilder.sort(new FieldSortBuilder("_uid").order(SortOrder.ASC));//也可以按_id字段进行升序排序

    SearchSourceBuilder的源过滤:默认情况下,搜索请求会返回文档_source的内容,但与Rest API中的内容一样,你可以覆盖此行为,例如,你可以完全关闭_source检索:

    sourceBuilder.fetchSource(false);
    该方法还接受一个或多个通配符模式的数组,以控制以更精细的方式包含或排除哪些字段:
    String[] includeFields = new String[] {"title", "user", "innerObject.*"};
    String[] excludeFields = new String[] {"_type"};
    sourceBuilder.fetchSource(includeFields, excludeFields);
    SearchSourceBuilder的请求结果高亮显示:通过在SearchSourceBuilder上设置HighlightBuilder,可以实现高亮搜索结果,通过将一个或多个HighlightBuilder.Field实例添加到HighlightBuilder,可以为每个字段定义不同的高亮行为。
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    HighlightBuilder highlightBuilder = new HighlightBuilder(); //创建一个新的HighlightBuilder。
    HighlightBuilder.Field highlightTitle = new HighlightBuilder.Field("title");  //为title字段创建字段高光色。
    highlightTitle.highlighterType("unified"); // 设置字段高光色类型。
    highlightBuilder.field(highlightTitle);   //将字段高光色添加到高亮构建器。
    HighlightBuilder.Field highlightUser = new HighlightBuilder.Field("user");
    highlightBuilder.field(highlightUser);
    searchSourceBuilder.highlighter(highlightBuilder);

    SearchSourceBuilder 更多api可以参考链接文章,归纳的很详细了,不再过多引述。



    
    

     写一个controller用于测试

    import java.io.IOException;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import com.slowcity.admin.service.ElasticSearchService;
    
    @RestController 
    @RequestMapping("/test")
    public class TestResource {
        
        @Autowired
        private ElasticSearchService elasticSearchService;
        private static final Logger log = LoggerFactory.getLogger(TestResource.class);
        //条件 查询 
        @PostMapping("/v1/test")
        public String query( ) {
            String queryResult =null;
            try {
                queryResult = elasticSearchService.search();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return queryResult;
        }
    }

    首先在es中维护几条数据,如下:

     

     postman测试一下,结果如下:

     

    【end】

  • 相关阅读:
    基于WINCE嵌入式系统的FM1702的读写器(2)
    WINCE 按键驱动编写
    WinCE内存调整
    USB模块
    网络模块
    wince6.0下ov9650的图像保存
    Windows CE内存泄漏
    MPEG4解码函数
    centos 7 gitlab安装 李刚
    docker 17.12.0ce 空间大小和容器大小限制修改 李刚
  • 原文地址:https://www.cnblogs.com/slowcity/p/11727579.html
Copyright © 2011-2022 走看看