es之查询大汇总

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

记录一下最近用到的es查询,感觉常见的应该都遇上了,下午抽空更新。

又拖,一直拖,终于闲下来了,现在开始写吧。。。

es作为一款基于文档的非关系型数据库,elasticsearch,既然带有search,所以,可以猜到他的检索能力是非常出色的,今天,我想记录一下我最近用的es的查询分析功能,先说基本查询,然后模糊查询,最后说聚合查询吧

一,简单查询

1,先看一下java api

SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
RangeQueryBuilder rangequerybuilder = QueryBuilders
        .rangeQuery("date")
        .from(startTime).to(endTime);
TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery(key, value);
TermQueryBuilder termQueryBuilderNot = QueryBuilders.termQuery("status", "0");
searchRequestBuilder = searchRequestBuilder.setQuery(QueryBuilders.boolQuery().must(rangequerybuilder).must(termQueryBuilder).mustNot(termQueryBuilderNot))
        .setFrom(0).setSize(10);
SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();

上面是java查询es最基本的api。

client.prepareSearch(index);指定index,提示:es6中每个index只能有一个type,所以查询时type存在的意义不大,且es支持查询时不带type

RangeQueryBuilder rangequerybuilder 可以限定范围

TermQueryBuilder termQueryBuilder 可以查询等于某值的结果,拼装searchRequestBuilder时,配合.mustNot(),must()使用

searchRequestBuilder用于最后拼装上面的查询限定条件

.setFrom(0).setSize(0)代表从查询结果的第0个开始显示,共显示10个

.execute().actionGet();这个是真正的向es集群发送请求的语句

了解了基本的查询之后,我们在说一下模糊查询

二,模糊查询

我用到的是正则匹配,比如实际值是https://my.oschina.net/u/3796880/blog/write/3042734,但你想通过https://my.oschina.net/u/3796880/blog/write就可以查出来,后面的值模糊匹配,ok,开始

WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery(key, value);

key是es中的字段名,value是“https://my.oschina.net/u/3796880/blog/write*”,道理懂吧。值“*oschina.net/u/3796880/blog*”也可以查询来,总之就是正则嘛

同理前缀查询道理也一样

PrefixQueryBuilder prefixQueryBuilder=QueryBuilders.prefixQuery(key,value)

我暂时没用,想用的同学可自行了解一下

说道这里,我想到自己踩过的一个坑

TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery(key, values);
TermsQueryBuilder 支持查询某字段的多个值,比如查询语言是java,c,c++的数据,可以这么写

String values[]={"java","c","python"};
    TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("language", values);

是不是很方便?但是,有一天,需求变了,language字段不是精准查询,要改为模糊匹配。第一反应是so eazy,把wildcardQuery改为wildcardsQuery不得了,但。。。最后发现es没提供这个方法。。。,最后只能一个一个加了

但怎么加呢,他们之间是或的关系,理所当然这样写

WildcardQueryBuilder wildcardQueryBuilder1 = QueryBuilders.wildcardQuery(key, value1);
WildcardQueryBuilder wildcardQueryBuilder2 = QueryBuilders.wildcardQuery(key, value2);
WildcardQueryBuilder wildcardQueryBuilder3 = QueryBuilders.wildcardQuery(key, value3);

最后

QueryBuilders.boolQuery().must(其他QueryBuilders).should(wildcardQueryBuilder1).should(wildcardQueryBuilder2).should(wildcardQueryBuilder3)

但,最后发现查不到数据,最后解决办法:需要外面包一层must

BoolQueryBuilder queryBuilder= QueryBuilders.boolQuery().should(wildcardQueryBuilder1).should(wildcardQueryBuilder2).should(wildcardQueryBuilder3);
QueryBuilders.boolQuery().must(其他QueryBuilders).must(queryBuilder);

完美解决!

三、聚合查询

1、某字段聚合

最常见的需求,查询某字段分组后的个数,比如男生几个,女生几个,类似于sql中的group by

AggregationBuilder aggregationBuilder = AggregationBuilders.terms("sex").field("sex).size(1000);

第一个“sex”代表你给聚合完的数据起的名字

第二个“sex”,即.field("sex)代表真实的es中存在的,你想要分组的字段名

1000,代表本次查询支持最大的buckets数量,此例中,不出意外,最大是3,非男即女或空。所以此处的1000改为3也无所谓。即有几个分组就会有几个buckets。

2、简单运算

计算平均值 
AggregationBuilders.avg(自己取的名字).field(实际字段名)
计算某字段的50线,60线...95线,99线
AggregationBuilders.percentiles(自己取的名字).field(实际字段名).percentiles(50.0, 60.0, 70.0, 80.0, 90.0, 95.0, 99.0);
将某字段的值按大小分组

如,统计工资在0-100,100-150,150-200,大于200的个数 RangeAggregationBuilder rangeQueryBuilder2 = AggregationBuilders.range("tolerating").addRange(0, 10000).field("load.duration");

RangeAggregationBuilder rangeQueryBuilder1 = AggregationBuilders.range("least").addRange(0, 100).field("wages");
RangeAggregationBuilder rangeQueryBuilder2 = AggregationBuilders.range("less").addRange(100, 150).field("wages");
RangeAggregationBuilder rangeQueryBuilder3 = AggregationBuilders.range("many").addRange(150, 200).field("wages");
RangeAggregationBuilder rangeQueryBuilder4 = AggregationBuilders.range("mush").addRange(200, 10000000000).field("wages");

然后再searchRequestBuilder中加入聚合

SearchResponse searchResponse = searchRequestBuilder.addAggregation(rangeQueryBuilder1)
                                                    .addAggregation(rangeQueryBuilder2)
                                                    .addAggregation(rangeQueryBuilder3)
                                                    .addAggregation(rangeQueryBuilder4)

这里有个不方便的地方,比如大于200的,这个不好限制,写成【200,1000000000】确实结果大概率是对的,但加入真的有一个人,工资超级高,那你就把它,它,哈哈,落下了。怎么办呢?

大于200:RangeAggregationBuilder rangeQueryBuilder1 = AggregationBuilders.range("must").addUnboundedFrom("200").field("wages");
小于100:RangeAggregationBuilder rangeQueryBuilder1 = AggregationBuilders.range("must").addUnboundedTo("100").field("wages");
时间分组 
方法1:
AggregationBuilders.dateHistogram(自己取的名字).field(实际字段名).dateHistogramInterval(DateHistogramInterval.SECOND);表示按秒分组 
还有DateHistogramInterval.MINUTE,DateHistogramInterval.HOURDate,HistogramInterval.DAY
方法2:
AggregationBuilders.dateHistogram(自己取的名字).field(实际字段名).interval(毫秒值);

3、多重聚合

AggregationBuilder firstAggregationBuilder = AggregationBuilders.terms(agg1).field(agg1).size(1000);
AvgAggregationBuilder secondAggregationBuilder = AggregationBuilders.avg(agg2).field(agg2);
firstAggregationBuilder.subAggregation(secondAggregationBuilder)
最后searchRequestBuilder.addAggregation(firstAggregationBuilder)即可

四、哈哈哈

1,有不对或不懂的地方,私信我,或者评论区评论都可以

2,有实现不了的查询需求,发出来,大家一起想想,哦了

转载于:https://my.oschina.net/u/3796880/blog/3042734

你可能感兴趣的:(es之查询大汇总)