• RestHighLevelClient查询es


     本篇分享的是es官网推荐的es客户端组件RestHighLevelClient的使用,其封装了操作es的crud方法,底层原理就是模拟各种es需要的请求,如put,delete,get等方式;本篇主要分享常用查询,希望能给大家带来好的帮助;

    • 分页查询
    • 条件查询

      1. 文本模糊匹配
      2. 时间范围匹配
    • 超时设置

      1. es超时时间
      2. RestHighLevelClient发送请求的http响应超时时间
    • 排序
    • 指定返回列
    • 模拟一个post获取es数据

    准备工作

    本人es服务端的版本是5.6.x,因此RestHighLevelClient建议同样引入相同主版本的包,相关参考文档(link):

     1         <dependency>
     2             <groupId>org.elasticsearch.client</groupId>
     3             <artifactId>elasticsearch-rest-high-level-client</artifactId>
     4             <version>5.6.16</version>
     5         </dependency>
     6 
     7         <dependency>
     8             <groupId>com.alibaba</groupId>
     9             <artifactId>fastjson</artifactId>
    10             <version>1.2.56</version>
    11             <scope>compile</scope>
    12         </dependency>

    作为客户端来说,我们需要知道es服务的ip:端口,以此来连接到服务端,对于es来说连接服务端其实就是往这个ip:端口上发送各种格式请求参数,如下创建个restclient:

    1     public RestHighLevelClient client() {
    2         Assert.requireNonEmpty(this.hosts, "无效的es连接");
    3         return new RestHighLevelClient(
    4                 RestClient.builder(this.hosts).build()
    5         );
    6     }

    分页查询

    作为客户端来说resthighlevelclient的查询操作及其简单,只需要如下简短代码即可操作查询:

     1             SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
     2             SearchRequest rq = new SearchRequest();
     3             //索引
     4             rq.indices(index);
     5             //各种组合条件
     6             rq.source(sourceBuilder);
     7 
     8             //请求
     9             System.out.println(rq.source().toString());
    10             SearchResponse rp = client().search(rq);

    如上模板我们知道要完成一次查询,需要知道对应的索引和各种业务查询条件;索引是必须的,至于条件这里先来分页吧,可以通过如下方式设置页码:

    1             from = from <= -1 ? 0 : from;
    2             size = size >= 1000 ? 1000 : size;
    3             size = size <= 0 ? 15 : size;
    4             //其实位置
    5             sourceBuilder.from(from);
    6             //每页数量
    7             sourceBuilder.size(size);

    条件查询

    对于查询来说通常都有各种and和or的条件,可以通过SearchSourceBuilder的must和should来设置and和or关系,这里用到了must;

    1.文本模糊匹配
    对于es关键字或单词的查询我们可以借助QueryBuilders.wildcardQuery方法来操作,只需要指定es中对应的列和要查询的内容即可:

    1             //模糊匹配
    2             boolQueryBuilder.must(QueryBuilders.wildcardQuery(k, v.toString()));

    2.时间范围匹配
    相对时间条件来说,通常的需求都是按照范围来查询的,这里可以借助QueryBuilders.rangeQuery指定es中某列(k)的范围匹配:

    1    boolQueryBuilder.must(
    2                         QueryBuilders.rangeQuery(k).
    3                                 gte(format.format(mapV.get("start"))).
    4                                 lt(format.format(mapV.get("end"))));

    超时设置

    使用RestHighLevelClient作为查询端,需要注意的超时时间有两种:es本身需要的时间和Rest发送http的响应时间

    1.es超时时间
    对于es服务端来说往往需要设置一下查询超时时间,尽管es是分布式查询较快并建立在多个lucence基础上聚合的查询,也需要设置超时时间,避免由于数据量过大或集群过大导致查询缓慢问题;

    1     sourceBuilder.timeout(new TimeValue(timeOut, TimeUnit.SECONDS));

    2.RestHighLevelClient发送请求的http响应超时时间
    对应http来说往往会有一个响应的时长,超过时长后将不能再获取到数据,RestHighLevelClient作为以http方式请求es客户端这点需要注意;比如es查询需要10s,但是http设置了5s,数据就无法正常返回;

    1         return new RestHighLevelClient(
    2                 RestClient.builder(this.hosts).
    3                         setMaxRetryTimeoutMillis(60 * 1000).  //设置http客户请求时长
    4                         build()
    5         );

    排序

    排序在业务中也是常用,es提供了默认排序和自定义排序,默认排序通常都是_score来排的,如下参数:

    如果自定义列来排序,可以通过如下方式:

    1       sourceBuilder.sort(new FieldSortBuilder(k).order(v ? SortOrder.ASC : SortOrder.DESC));

    指定返回列

    对应查询通常会指定一些返回列,就sql查询来说select *通常都比select cols要慢,一个原因是数据量少了有可能走了索引;es其实也同样,指定返回列可减少返回数据体量;

    1             //返回和排除列
    2             if (!CollectionUtils.isEmpty(includeFields) || !CollectionUtils.isEmpty(excludeFields)) {
    3                 sourceBuilder.fetchSource(includeFields, excludeFields);
    4             }

    模拟一个post获取es数据

    如上就是查询es常用一些参数说明,配置及心得;下面给出完整的示例代码:

     1   /**
     2      * @param index
     3      * @param from
     4      * @param size
     5      * @param where
     6      * @param sortFieldsToAsc
     7      * @param includeFields
     8      * @param excludeFields
     9      * @param timeOut
    10      * @return
    11      */
    12     public List<Map<String, Object>> searchIndex(String index, int from, int size, Map<String, Object> where,
    13                                                  Map<String, Boolean> sortFieldsToAsc, String[] includeFields, String[] excludeFields,
    14                                                  int timeOut) {
    15         SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
    16         try {
    17             SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    18             //条件
    19             if (where != null && !where.isEmpty()) {
    20                 BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    21                 where.forEach((k, v) -> {
    22                     if (v instanceof Map) {
    23                         //范围选择map  暂定时间
    24                         Map<String, Date> mapV = (Map<String, Date>) v;
    25                         if (mapV != null) {
    26                             boolQueryBuilder.must(
    27                                     QueryBuilders.rangeQuery(k).
    28                                             gte(format.format(mapV.get("start"))).
    29                                             lt(format.format(mapV.get("end"))));
    30                         }
    31                     } else {
    32                         //普通模糊匹配
    33                         boolQueryBuilder.must(QueryBuilders.wildcardQuery(k, v.toString()));
    34                     }
    35                 });
    36                 sourceBuilder.query(boolQueryBuilder);
    37             }
    38 
    39             //分页
    40             from = from <= -1 ? 0 : from;
    41             size = size >= 1000 ? 1000 : size;
    42             size = size <= 0 ? 15 : size;
    43             sourceBuilder.from(from);
    44             sourceBuilder.size(size);
    45 
    46             //超时
    47             sourceBuilder.timeout(new TimeValue(timeOut, TimeUnit.SECONDS));
    48 
    49             //排序
    50             if (sortFieldsToAsc != null && !sortFieldsToAsc.isEmpty()) {
    51                 sortFieldsToAsc.forEach((k, v) -> {
    52                     sourceBuilder.sort(new FieldSortBuilder(k).order(v ? SortOrder.ASC : SortOrder.DESC));
    53                 });
    54             } else {
    55                 sourceBuilder.sort(new ScoreSortBuilder().order(SortOrder.DESC));
    56             }
    57 
    58             //返回和排除列
    59             if (!CollectionUtils.isEmpty(includeFields) || !CollectionUtils.isEmpty(excludeFields)) {
    60                 sourceBuilder.fetchSource(includeFields, excludeFields);
    61             }
    62 
    63             SearchRequest rq = new SearchRequest();
    64             //索引
    65             rq.indices(index);
    66             //各种组合条件
    67             rq.source(sourceBuilder);
    68 
    69             //请求
    70             System.out.println(rq.source().toString());
    71             SearchResponse rp = client().search(rq);
    72 
    73             //解析返回
    74             if (rp.status() != RestStatus.OK || rp.getHits().getTotalHits() <= 0) {
    75                 return Collections.emptyList();
    76             }
    77 
    78             //获取source
    79             return Arrays.stream(rp.getHits().getHits()).map(b -> {
    80                 return b.getSourceAsMap();
    81             }).collect(Collectors.toList());
    82 
    83         } catch (Exception ex) {
    84             ex.printStackTrace();
    85         }
    86         return Collections.emptyList();
    87     }

    分享通过RestClient方式往es发送的请求参数以及模拟post方式发送参数获取es数据:

     1 {
     2   "from" : 0,
     3   "size" : 5,
     4   "timeout" : "60s",
     5   "query" : {
     6     "bool" : {
     7       "must" : [
     8         {
     9           "range" : {
    10             "timeStamp" : {
    11               "from" : "2019-05-23T19:17:59.000+0800",
    12               "to" : "2019-05-23T19:18:00.000+0800",
    13               "include_lower" : true,
    14               "include_upper" : false,
    15               "boost" : 1.0
    16             }
    17           }
    18         },
    19         {
    20           "wildcard" : {
    21             "data" : {
    22               "wildcard" : "",
    23               "boost" : 1.0
    24             }
    25           }
    26         }
    27       ],
    28       "disable_coord" : false,
    29       "adjust_pure_negative" : true,
    30       "boost" : 1.0
    31     }
    32   },
    33   "_source" : {
    34     "includes" : [ ],
    35     "excludes" : [
    36       "serverIp"
    37     ]
    38   },
    39   "sort" : [
    40     {
    41       "timeStamp" : {
    42         "order" : "desc"
    43       }
    44     }
    45   ]
    46 }

    有了上面参数,我们完全可以通过postman直接发post给es服务端,让其返回响应的数据而;resthighlevelclient作为http客户端就是帮我们完成了这部分封装:

  • 相关阅读:
    判断字符串是否包含某一个值方法
    生成一个随机手机号
    python 常用数据类型及操作方法
    selenium 常用的定位方法
    mysql 多表查询
    转载--python全栈开发学习
    Jenkins执行jmeter自动化脚本方法
    阅读方法
    pytorch学习
    英文阅读材料记录
  • 原文地址:https://www.cnblogs.com/wangrudong003/p/10959525.html
Copyright © 2020-2023  润新知