一、Elasticsearch的聚合

ES的聚合相当于关系型数据库里面的group by,例如查找在性别字段男女人数的多少并且按照人数的多少进行排序,在使用MySQL的时候,可以使用如下的句子

select sex,count(*) from table_name group by sex order by count(*)

在ES里面想要实现这种的语句,就叫做聚合,比如这种的聚合使用DSL语句的话如下所示:

GET /index/type/_search

{

"size":0,

"aggs": {

"agg_sex": {

"terms": {

"field":"sex"

}

}

}

}

这样就可以实现最以上例子中的group by的功能,当然这只是最简单的聚合的使用,在ES里面的聚合有多重多样的,比如说有度量聚合,可以用来计算某一个字段的平均值最大值等,在此给出一个简单的度量聚合的例子

GET /index/type/_search

{

"size":0,

"aggs": {

"agg_sex": {

"terms": {

"field":"sex"

},

"agg_age": {

"avg_age": {

"avg": {

"field":"age"

}

}

}

}

}

}

这个DSL语句就是将先按照性别进行聚合,并且对不同的性别给出一个平均的年龄,使用之后ES的给出结果如下所示:

{

...

"aggregations": {

"agg_sex": {

"buckets": [

{

"key":"male",

"doc_count":4,

"avg_age": {

"value":25

}

},

{

"key":"female",

"doc_count":2,

"avg_age": {

"value":23

}

}

]

}

}

...

}

在度量聚合里面有min,max,sum,avg聚合等,还有stats,extern_stats等聚合,其中stats的聚合给出的信息会包括min,max,count等基本的信息,更多详细的细节请参考ES官网给出的指导https://www.elastic.co/guide/en/elasticsearch/guide/current/aggregations.html

以上只是给出的度量聚合,但是在实际中我们经常使用的是桶聚合,什么是桶聚合呢,个人理解就是将符合某一类条件的文档选出来,所有的某一类的聚合就称为桶,例如你可以按照某一个分类将所有的商品聚合起来,这种情况下就可以认为某一个分类的商品称为一个桶,下面将详细介绍几个常用的桶聚合,并且会给出Java使用时候的代码

二、桶聚合

桶聚合是在实际使用时候用处比较多的一种聚合,简单的桶聚合包括term聚合,range聚合,date聚合,IPV4聚合等聚合,因为自己使用的仅仅是其中的三个,在此就简单的介绍三个,分别是term聚合,range聚合,以及date聚合

1、term聚合

term聚合就是第一部分给出的简单的例子,按照不同的字段进行聚合

2、range聚合

range聚合为按照自定义的范围来创造桶,将每一个范围的数据进行聚合,并且这个聚合一般适用于字段类型为long或者int,double的字段,可以进行直接的聚合,例如,我们想统计不同年龄段的人的个数,DSL如下所示:

GET /index/type/_search

{

"aggs": {

"agg_age": {

"field":"age"

"ranges": [

{ "to":18},

{ "from":19,"to":50},

{"from":51}

]

}

}

}

3、daterange聚合

date range聚合和range聚合类似,但是所使用的类型是datetime这种类型,使用的时候与range有些区别,给出一个简单的使用date range聚合的DSL例子,如下所示:

GET /index/type/_search

{

"aggs": {

"agg_year": {

"field":"date"

"ranges": [

{ "to":"2008-08-08"},

{ "from":"2008-08-09","to":"2012-09-01"},

{"from":"2012-09-02"}

]

}

}

}

上面的DSL是简单的按照时间格式进行区间的聚合,但是有些时候我们可能想要一些按照年份聚合或者月份聚合的情况,这个时候应该怎么办呢?在date range里面可以指定日期的格式,例如下面给出一个按照年份进行聚合的例子:

GET /index/type/_search

{

"aggs": {

"agg_year": {

"field":"date"

"format":"YYYY",

"ranges": [

{ "to":"1970"},

{ "from":"1971","to":"2012"},

{"from":"2013"}

]

}

}

}

我们可以指定格式来进行聚合

三、对于上述三种聚合java的实现

首先先给出一个具体的使用ES Javaapi实现搜索并且聚合的完整例子,例子中使用的是terms聚合,按照分类id,将所有的分类进行聚合

publicvoidaggsearch() {

init();

SearchResponse response = null;

SearchRequestBuilder responsebuilder = client.prepareSearch("iktest")

.setTypes("iktest").setFrom(0).setSize(250);

AggregationBuilder aggregation = AggregationBuilders

.terms("agg")

.field("category_id")

.subAggregation(

AggregationBuilders.topHits("top").setFrom(0)

.setSize(10)).size(100);

response = responsebuilder.setQuery(QueryBuilders.boolQuery()

.must(QueryBuilders.matchPhraseQuery("name","中学历史")))

.addSort("category_id", SortOrder.ASC)

.addAggregation(aggregation)// .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)

.setExplain(true).execute().actionGet();

SearchHits hits = response.getHits();

Terms agg = response.getAggregations().get("agg");

System.out.println(agg.getBuckets().size());

for(Terms.Bucket entry : agg.getBuckets()) {

String key = (String) entry.getKey(); // bucket key

longdocCount = entry.getDocCount();// Doc count

System.out.println("key "+ key +" doc_count "+ docCount);

// We ask for top_hits for each bucket

TopHits topHits = entry.getAggregations().get("top");

for(SearchHit hit : topHits.getHits().getHits()) {

System.out.println(" -> id "+ hit.getId() +" _source [{}]"

+ hit.getSource().get("category_name"));

;

}

}

System.out.println(hits.getTotalHits());

inttemp =0;

for(inti =0; i

// System.out.println(hits.getHits()[i].getSourceAsString());

System.out.print(hits.getHits()[i].getSource().get("product_id"));

// if(orderfield!=null&&(!orderfield.isEmpty()))

// System.out.print("\t"+hits.getHits()[i].getSource().get(orderfield));

System.out.print("\t"

+ hits.getHits()[i].getSource().get("category_id"));

System.out.print("\t"

+ hits.getHits()[i].getSource().get("category_name"));

System.out.println("\t"

+ hits.getHits()[i].getSource().get("name"));

}

}

}

以上的例子实现的是按照category_id字段进行分类的聚合,并且将在name字段查找包含“中学历史”的这个词,并且按照category_id进行排序,在此给出的只是一个搜索实现的函数,里面的字段名字,以及index,type等很多字段均为自己定义的index里面的名字,上面给出的是terms聚合时候的代码,如果使用的是range聚合或者date range聚合,只需要改变

aggregation就可以

使用range聚合的时候:

aggregation = AggregationBuilders.range("agg")

.field("price").addUnboundedTo(50)

.addRange(51,100).addRange(101,1000)

.addUnboundedFrom(1001);

使用date range聚合的时候:

aggregation = AggregationBuilders.dateRange("agg")

.field("date").format("yyyy")

.addUnboundedTo("1970").addRange("1970","2000")

.addRange("2000","2010").addUnboundedFrom("2009");

以上所有的聚合均是先过滤搜索,然后对于召回得到的结果进行一个聚合,例如我们在name字段搜索中学历史这个词,最终得到四个分类分别为1,2,3,4那么聚合的时候就是这四个分类,但是有时候我们可能会需要对于搜索的结果进行一个过滤,但是我们不想对聚合的结果进行过滤,那么我们就要使用一下的部分了

四、先聚合再过滤

以上将的简单的聚合都是先过滤或者搜索,然后对结果进行聚合,但是有时候我们需要先进行聚合,然后再对结果进行一次过滤,但是我们不希望这个时候聚合会发生变化,什么时候会遇到这种情况呢,我们以美团为例做一个说明,在主页我们直接点解美食,得到如下所示的图

点美食之后出现全部的分类,包括各种的菜系,下面我们点一个具体的菜系

从程序上来说,我们点第二次菜系的时候,出现的所有的菜品均是烤串之类的菜品了,但是在分类里面还是所有的分类都会有,如果按照之前的ES的聚合,会将所有搜索出来的品的分类进行一个聚合,但是点完烤串之后,所有的分类都是烤串了,那么就应该所有的分类只有一个烤串了,不应该有其他的,这样的话肯定是不可以的,那么如何才能实现这种聚合的,这个时候我们就需要先聚合,然后进行再次的过滤,但是过滤的时候并不影响之前的聚合结果,这就是先聚合再过滤,在ES里面也有这种情况的考虑,这个时候使用的是postfilter

postfilter解决了仅仅过滤搜索结果,但是并不影响聚合结果,下面给出一个java使用时候的例子以及比较

函数一为第三部分给出的完整的搜索函数,按照分类聚合

函数二的改变只是对于一的

response = responsebuilder.setQuery(QueryBuilders.boolQuery()

.must(QueryBuilders.matchPhraseQuery("name","中学历史")))

.addSort("category_id", SortOrder.ASC)

.addAggregation(aggregation)

.setPostFilter(QueryBuilders.rangeQuery("price").gt(1000).lt(5000))

.setExplain(true).execute().actionGet();

添加了按照price进行过滤,最后结果显示,聚合的结果两次完全一样,但是函数二召回的结果为函数一结果的子集。

五、后续学习

如何多次的过滤以及召回,比如先过滤后聚合再过滤再次聚合然后再次过滤这种的应该如何实现,需要学习。

es 时间过滤java,Elasticsearch过滤与聚合的先后顺序java实现相关推荐

  1. Elasticsearch过滤与聚合的先后顺序java实现

    一.Elasticsearch的聚合 ES的聚合相当于关系型数据库里面的group by,例如查找在性别字段男女人数的多少并且按照人数的多少进行排序,在使用mysql的时候,可以使用如下的句子 sel ...

  2. 微服务项目之电商--19.ElasticSearch基本、高级查询和 过滤、结果过滤、 排序和聚合aggregations

    接上一篇 目录 3.查询 3.1.基本查询: 3.1.1 查询所有(match_all) 3.1.2 匹配查询(match) 3.1.3 多字段查询(multi_match) 3.1.4 词条匹配(t ...

  3. [Elasticsearch] 过滤查询以及聚合(Filtering Queries and Aggregations)

    原文地址为: [Elasticsearch] 过滤查询以及聚合(Filtering Queries and Aggregations) 本章翻译自Elasticsearch官方指南的Filtering ...

  4. java操作es聚合操作并显示其他字段_java使用elasticsearch分组进行聚合查询过程解析...

    这篇文章主要介绍了java使用elasticsearch分组进行聚合查询过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 java连接elas ...

  5. Elasticsearch Java API 分组、聚合、嵌套相关查询

    Elasticsearch Java API 分组.聚合.嵌套相关查询 翼支付监控系统正使用es做后端存储,这边我们是将日志计算处理过后的数据通过kafka储存到es.选择用es作为数据储存端是考虑到 ...

  6. es java api 查询_es聚合查询javaapi

    查询节气详情 package net.apishop.www.controller; import import import import import import import import i ...

  7. java straem 过滤_Java Stream 过滤器

    Java Stream 过滤器教程展示了如何使用过滤操作过滤 Java 流. Java 流 Java 流是来自源的支持聚合操作的一系列元素. 流不存储元素. 元素是按需计算的. 元素是从数据源(如集合 ...

  8. java正则表达式 过滤特殊字符的正则表达式

    在网上找了好久也没找到个合适的正则表达式以过滤特殊字符:自己学习了下,写了两个,实现要求. Java代码 // 过滤特殊字符 public static String StringFilter(Str ...

  9. java列出文件正则过滤_JAVA正则表达式过滤文件的实现方法

    java正则表达式过滤文件的实现方法 正则表达式过滤文件列表,听起来简单,如果用java实现,还真需要一番周折,本文简析2种方式 1.适用于路径确定,文件名时正则表达式的情况(jdk6的写法) Str ...

最新文章

  1. 2014025687《嵌入式系统程序设计》第七周学习总结
  2. Django里自定义用户登陆及登陆后跳转到登陆前页面的实现
  3. [vue] 为什么data属性必须声明为返回一个初始数据对应的函数呢?
  4. Linux学习总结(16)——CentOS 下 Nginx + Tomcat 配置负载均衡
  5. WinCE 控制面板和驱动通信
  6. id图像上传,方便超链接。
  7. document.all用法
  8. angular js权威指南笔记
  9. php tp admin怎么安装,TP的配置及安装 · Thinkphp5.1+AdminLTE内容管理系统(商城版) 请不要购买 到群上下载源码 · 看云...
  10. 小散量化炒股记|Python也能量化财务指标!教你用净资产收益率选股!
  11. 深度清理mac磁盘空间的方法,方方面面都清理干净
  12. Linux各目录的作用
  13. Panoply地理网格绘制软件
  14. 存储器块清零c语言版,存储器块清零实验
  15. SpringBoot配置全局的异常捕获
  16. 机器学习 数据预处理之数据打标签
  17. 3d怎么把两个面拼接在一起_720全景视频接缝拼接教程
  18. 自定义表单、自定义流程、自定义页面、自定义报表应用开发平台
  19. JGJT98-2010 砌筑砂浆配合比设计规程 免费下载
  20. Mybatis代码实例

热门文章

  1. Azure虚拟机计费模式
  2. torchtext使用-- 单标签多分类任务TREC
  3. 《区域经济分析方法》读书笔记
  4. The Foundry NUKE 12 mac版(电影特效合成制作软件)
  5. php源码二次开发的技术,Thinkphp二次开发威客RW平台源码详细搭建教程(技术分享帖)-一颗优雅草科技yungui...
  6. App Icon Gear App 图标制作工具
  7. Sublime Text 下载-设置切换中文版
  8. 计算机图形辐照度学、光度学
  9. 2021长城杯pwn部分wp
  10. 《真正的程序员不要使用PASCAL》