前言:
ES中的搜索查询,简单说就是根据查询条件匹配查询结果。网上的例子比较简单,这里我以一个比较复杂的DSL结构化查询语句为例子,看看用java的API如何描述这个查询语句。
其中涉及组合查询、聚合查询。
建议:
最好先下载一份ES的Java最新的API,对照着看效果会比较棒。
1、建立连接:
java连接ES集群的方式还挺多,最常用的应该是TransportClient。
它作为一个外部访问者,请求ES的集群,对于集群而言,它是一个外部因素。
Settings esSettings = Settings.builder()
.put("cluster.name", clusterName) //设置ES实例的名称
.put("client.transport.sniff", true) //自动嗅探整个集群的状态, 把集群中其他ES节点的ip添加到本地的客户端列表中
.build();
client = new PreBuiltTransportClient(esSettings);//初始化clie nt较老版本发生了变化,此方法有几个重载方法,初始化插件等。
//此步骤添加IP,至少一个,其实一个就够了,因为添加了自动嗅探配置
client.addTransportAddress(new InetSocketTransportAddress(In etAddress.getByName(ip), esPort));
注意,Java连接集群的端口一般是9300,HTTP端口一般是9200,集群名一定要设置正确。
2、组合查询:
这里我们将用Java的API描述这样一个DSL查询:
这个查询主要是查询某个索引,需要满足以下条件:
(1)logtime是一个描述时间的字段,他需要满足我们传入的开始时间和结束时间之间,这样一个时间段;
(2)kpi_code字段不能是“1111”、“2222”;
(3)asset是一个数组字段里面存储多个IP,我们需要模糊匹配我们传入的一个IP,即asset数组中需要包含我们传入的IP;
(4)is_steal字段严格匹配“1”;
(5)最后是一个聚合分析,按照指定的格式返回查询;
看不明白DSL的可以去补充一下,DSL查询,使用JAVA基本上就是把DSL语句描述出来。
:{
"size":0,
"query":{
"bool": {
"filter": [
{
"bool": {
"must": [
{
"range": {
"logtime": {
"gte": TOOL.moment(startday).format("YYYY-MM-DD")+"T00:00:00",
"lte": TOOL.moment(endday).format("YYYY-MM-DD")+"T23:59:59",
"include_lower": true,
"include_upper": true,
"boost": 1,
"time_zone": "+08:00"
}
}
},
{
"bool": {
"must_not": [
{
"match_phrase": {
"kpi_code": {
"query": "3086",
"slop": 0,
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
{
"bool": {
"must_not": [
{
"match_phrase": {
"kpi_code": {
"query": "3087",
"slop": 0,
"boost": 1
}
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
},
{
"wildcard": {
"asset": {
"wildcard": "*"+ip+"*",
"boost": 1
}
}
},
{
"bool": {
"must": [
{
"term": {
"is_steal": "1"
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
],
"adjust_pure_negative": true,
"boost": 1
}
}
]
}
},
"aggs":{
"gid":{
"terms":{"script": "return doc['logtime'].value+','+doc['gid'].value+','+doc['kpi_code'].value+','+doc['steal_stage'].value+','+doc['malname.keyword'].value+','+doc['event_level'].value","size":10000,"order":[{"_key": "asc"}]}
}
}
}
})
搜索查询使用的是SearchResponse,其主要工作在于如何构建查询器、聚合器。
/**
* 从ES中根据指定条件查询
* @param index 索引名
* @param query 查询器
* @param aggregation 聚合器
* @return
*/
public Aggregations searchFunction(String index, QueryBuilder query, AggregationBuilder aggregation){
SearchResponse response = this.client.prepareSearch(index)
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
.setQuery(query)
.addAggregation(aggregation)
.setFrom(0)
.setSize(0).setExplain(true).get();
//SearchHits hits = response.getHits();
Aggregations aggregations = response.getAggregations();
return aggregations;
}
search查询的语句基本就是这样,我们需要传入构建好的QueryBuilder 、AggregationBuilder ,就OK了。
下面重点说一下,QueryBuilder 和AggregationBuilder 的构建。
3、构建查询条件:
先贴出代码:
//嵌套查询
BoolQueryBuilder childQb1 = QueryBuilders.boolQuery();
childQb1.mustNot(QueryBuilders.matchPhraseQuery("kpi_code", "3086"));
BoolQueryBuilder childQb2 = QueryBuilders.boolQuery();
childQb2.mustNot(QueryBuilders.matchPhraseQuery("kpi_code", "3087"));
WildcardQueryBuilder childQb3= QueryBuilders.wildcardQuery("asset", "*"+ip+"*");
BoolQueryBuilder childQb4 = QueryBuilders.boolQuery();
childQb4.must(QueryBuilders.termQuery("is_steal", "1"));
RangeQueryBuilder rangeBuilder = new RangeQueryBuilder("logtime")
.gte(startDay+"T00:00:00").lte(endDay+"T23:59:59")
.timeZone("+08:00");
BoolQueryBuilder qb = QueryBuilders.boolQuery();
qb.filter(rangeBuilder).filter(childQb1).filter(childQb2).filter(childQb3).filter(childQb4);
//嵌套聚合
Script script = new Script("return doc['logtime'].value+','+doc['gid'].value+','+doc['kpi_code'].value+','+doc['steal_stage'].value+','+doc['malname.keyword'].value+','+doc['event_level'].value");
TermsAggregationBuilder aggresstionTwo = AggregationBuilders.terms("gid").script(script);
aggresstionTwo.size(10000);
//aggresstionTwo.order(BucketOrder.aggregation("_key", true));
Aggregations aggresstions = esUtil.searchFunction("jg_gaojing*", qb, aggresstionTwo);
嵌套查询中的BoolQueryBuilder 是最常用的。我们看到,对应DSL的每个查询命令都有对应。我建议从最里层的“bool”开始写,一层层嵌套直至最外层。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之家整理,本文链接:https://www.bmabk.com/index.php/post/10356.html