欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

RestHighLevelClient查询es

程序员文章站 2022-09-07 14:48:02
本篇分享的是es官网推荐的es客户端组件RestHighLevelClient的使用,其封装了操作es的crud方法,底层原理就是模拟各种es需要的请求,如put,delete,get等方式;本篇主要分享常用查询,希望能给大家带来好的帮助; 分页查询 条件查询 文本模糊匹配 时间范围匹配 超时设置 ......

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

  • 分页查询
  • 条件查询

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

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

准备工作

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

 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来排的,如下参数:

RestHighLevelClient查询es

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

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客户端就是帮我们完成了这部分封装:

RestHighLevelClient查询es