在常规数据库中,我们都知道有一个sql就是group,分组。如果主表只有对应的一个列记录的分组的ID,那么还好统计,比如说每本书book表,有一个分类catId,记录是属于哪一类的书,那么直接按照catId进行分组即可。可是在实际应用种,并非如此简单。一本书往往属于多个分类,比如:某本书既属于科技类书,又属于儿童类书,要求按照这两种条件进行筛选,都能筛选出来,如果要求按照分类进行统计数量,数据库怎么group?我们且抛开种种解决方案,来看看Elasticsearch里面对这种需求,是多么的容易统计。
首先,我们需要造些数据,需要用到一个模型,这个模型定义了一个type,就算类型吧,我们用这个属性来演示常规的group。还有一个catIds的列表模型,这个来解决我们上面描述的一本书对应多个分类的需求。模型定义如下:
import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.donlianli.es.ESUtils; /** * 这个是为分组定义的一个模型 * catIds通常为一对多的分类ID * @author donlian */ public class FacetTestModel implements Serializable { private static final long serialVersionUID = 3174577828007649745L; /** * 随便编写的一些值,type属性只能取这里面的其中一个 */ private String[] types= new String[]{ "type1","type2","type3","type4","type5","type6","type7", "type11","type12","type13","type14","type15","type16","type17" }; //主ID private long id; //类型,为types之一 private String type; /** * 所属分类,范围为1-50 */ private List<Integer> catIds; public FacetTestModel(){ Random r = new Random(); int n = Math.abs(r.nextInt()); int index = n%14; this.type = types[index]; this.id = Math.abs(r.nextLong()); n = n%50; catIds = new ArrayList<Integer>(); catIds.add(n); int ys = n%3; if(ys!=0){ for(int i=1;i<ys+1;i++){ catIds.add(n+i); } } } public static void main(String[] argv){ for(int i=0;i<10;i++){ FacetTestModel f = new FacetTestModel(); System.out.println(ESUtils.toJson(f)); } } public long getId() { return id; } public void setId(long id) { this.id = id; } public String getType() { return type; } public void setType(String type) { this.type = type; } public List<Integer> getCatIds() { return catIds; } public void setCatIds(List<Integer> catIds) { this.catIds = catIds; } }
接着就是初始化数据。
import org.elasticsearch.action.bulk.BulkRequestBuilder; import org.elasticsearch.action.bulk.BulkResponse; import org.elasticsearch.action.index.IndexRequestBuilder; import org.elasticsearch.client.Client; import com.donlianli.es.ESUtils; import com.donlianli.es.model.FacetTestModel; public class BulkIndexTest { public static void main(String[] args) { Client client = ESUtils.getClient(); BulkRequestBuilder bulkRequest = client.prepareBulk(); for(int i=0;i<10;i++){ String json = ESUtils.toJson(new FacetTestModel()); IndexRequestBuilder indexRequest = client.prepareIndex("test", "test") //指定不重复的ID .setSource(json).setId(String.valueOf(i)); //添加到builder中 bulkRequest.add(indexRequest); } BulkResponse bulkResponse = bulkRequest.execute().actionGet(); if (bulkResponse.hasFailures()) { System.out.println(bulkResponse.buildFailureMessage()); } } }
接下来,我们首先对type进行统计。在elasticsearch中,分组的功能叫facet,不知道为啥起这个名称。总之,就是对type的每一个值的数量进行统计,注意,要设置里面的size条件,否则默认只返回10个。
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.search.facet.FacetBuilders; import org.elasticsearch.search.facet.Facets; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.TermsFacetBuilder; import com.donlianli.es.ESUtils; public class GroupTest { public static void main(String[] argv){ Client client = ESUtils.getClient(); TermsFacetBuilder facetBuilder = FacetBuilders.termsFacet("typeFacetName"); facetBuilder.field("type").size(Integer.MAX_VALUE); facetBuilder.facetFilter(FilterBuilders.matchAllFilter()); SearchResponse response = client.prepareSearch("test") .setTypes("test") .addFacet(facetBuilder) .setFilter(FilterBuilders.matchAllFilter()) .execute() .actionGet(); Facets f = response.getFacets(); //跟上面的名称一样 TermsFacet facet = (TermsFacet)f.getFacets().get("typeFacetName"); for(TermsFacet.Entry tf :facet.getEntries()){ System.out.println(tf.getTerm()+"\t:\t" + tf.getCount()); } client.close(); } }
运行程序后,大概得到如下结果:
type3 : 4 type7 : 1 type6 : 1 type4 : 1 type13 : 1 type12 : 1 type11 : 1
正好10个。初始化代码能对的上。
下面,我们就要对catIds进行统计了,再统计之前,我们先看看es里面都存储的是那些数据。
{id=3683174899323317453, catIds=[4, 5], type=type3} {id=271209313870366004, catIds=[26, 27, 28], type=type3} {id=348654892174153835, catIds=[41, 42, 43], type=type4} {id=6826187683023110944, catIds=[46, 47], type=type7} {id=3437591661789488747, catIds=[22, 23], type=type3} {id=6365837443081614150, catIds=[37, 38], type=type11} {id=2387331048448677498, catIds=[20, 21, 22], type=type3} {id=5595404824923951817, catIds=[31, 32], type=type13} {id=3593797446463621044, catIds=[30], type=type12} {id=5824112111832084165, catIds=[1, 2], type=type6}
怎么对catIds进行统计呢,代码跟上面进行单个统计一样。
import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.index.query.FilterBuilders; import org.elasticsearch.search.facet.FacetBuilders; import org.elasticsearch.search.facet.Facets; import org.elasticsearch.search.facet.terms.TermsFacet; import org.elasticsearch.search.facet.terms.TermsFacetBuilder; import com.donlianli.es.ESUtils; public class GroupTest2 { public static void main(String[] argv){ Client client = ESUtils.getClient(); TermsFacetBuilder facetBuilder = FacetBuilders.termsFacet("catIdName"); facetBuilder.field("catIds").size(Integer.MAX_VALUE); facetBuilder.facetFilter(FilterBuilders.matchAllFilter()); SearchResponse response = client.prepareSearch("test") .setTypes("test") .addFacet(facetBuilder) .setFilter(FilterBuilders.matchAllFilter()) .execute() .actionGet(); Facets f = response.facets(); //跟上面的名称一样 TermsFacet facet = (TermsFacet)f.getFacets().get("catIdName"); for(TermsFacet.Entry tf :facet.entries()){ System.out.println("键:"+tf.getTerm()+"\t;数量:\t" + tf.getCount()); } client.close(); } }
运行结果:
键:22 ;数量: 2 键:47 ;数量: 1 键:46 ;数量: 1 键:43 ;数量: 1 键:42 ;数量: 1 键:41 ;数量: 1 键:38 ;数量: 1 键:37 ;数量: 1 键:32 ;数量: 1 键:31 ;数量: 1 键:30 ;数量: 1 键:28 ;数量: 1 键:27 ;数量: 1 键:26 ;数量: 1 键:23 ;数量: 1 键:21 ;数量: 1 键:20 ;数量: 1 键:5 ;数量: 1 键:4 ;数量: 1 键:2 ;数量: 1 键:1 ;数量: 1
再和上面的数据对对,是不是除了22,其他的都是一个?
在分组这方面,ES真的很强大,除了上面的支持列表分组外,还支持范围分组rangeFacet,多个分组可以一次全部发送给ES等等,更多功能,大家还是自己多多验证。
对这类话题感兴趣?欢迎发送邮件至donlianli@126.com
关于我:邯郸人,擅长Java,Javascript,Extjs,oracle sql。
更多我之前的文章,可以访问 我的空间
相关推荐
而“elasticsearch聚合值过滤”是ES聚合功能的一个高级应用场景,它允许我们根据聚合计算出的结果来进一步筛选文档,即在聚合后的基础上进行过滤操作。这一特性在数据分析和报表生成时非常有用,能够帮助我们得到更...
方法如果传总页数了,es就不用查询总页数,直接通过开始位置到结束位置取数即可
Elasticsearch的聚合功能允许用户对数据进行汇总和分析,其中桶聚合和度量聚合是两种常用的聚合类型。本文将详细探讨这两种聚合的区别及其应用场景。 桶聚合和度量聚合在Elasticsearch中扮演着不同的角色,它们共同...
Elasticsearch聚合之Terms Elasticsearch中的Terms聚合是一种常用的聚合方式,用于对文档中的某个字段进行分组统计。Terms聚合可以对文档中的某个字段进行分组,并统计每个组中的文档数量。 在Elasticsearch中,...
elasticsearch聚合
在 Elasticsearch (ES) 中,聚合(Aggregations)是一种强大的功能,允许我们对索引中的数据进行统计分析,如求平均值、计数、分桶等。而在某些场景下,我们可能需要在聚合的基础上进一步过滤结果,即基于聚合的结果...
ES 聚合查询结果转换成相应的对象集合,ES 聚合查询结果转换成相应的对象集合
根据提供的文件信息,我们可以推断出本篇文章将围绕Elasticsearch 6.2.2版本进行详细介绍,包括其下载方式、主要功能特性以及在实际应用中的常见用途。 ### Elasticsearch简介 Elasticsearch是一款基于Lucene的...
ElasticSearch对数据进行聚合并对聚合结果值进行过滤查询
Elasticsearch(简称ES)是一款强大的开源搜索引擎,广泛应用于数据检索、分析和管理。作为分布式、RESTful风格的搜索和数据分析引擎,Elasticsearch能够提供实时、高可用性以及可扩展的搜索功能。在进行日常的数据...
Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监控堆栈。 Elasticsearch 为所有类型的数据提供近乎实时的...
5. **高级查询**: Elasticsearch支持丰富的查询语法,如匹配查询、范围查询、布尔查询等,以及聚合功能,如术语聚合、桶聚合等,可用于复杂的数据分析和报表生成。 6. **性能优化**: 为了提升性能,可以设置映射...
(狂神)ElasticSearch快速入门笔记,ElasticSearch基本操作以及爬虫(Java-ES仿京东实战),包含了小狂神讲的东西,特别适合新手学习,笔记保存下来可以多看看。好记性不如烂笔头哦~,ElasticSearch,简称es,es是一个...
多弹性搜索头,对著名的 Elasticsearch Head 的改进 1.保存和存储几个Elasticsearch端点 2.索引选项卡中的更多列 3. 任何请求现在都可以像 /_cat/indices 一样处理 JSON 返回 4. 更简约的外观(更小的字体等...) ...
聚合查询分页测试termsAgg.size(2147483647); //指定最大统计显示多少行步骤1:全量聚合,size设置为: 2147483647。 ES5.X/6.X版本设置为2147483647 ,它等于2^31-1,请看该地方代码
4. **聚合分析**:学习如何使用 Elasticsearch 的聚合功能进行数据统计和分析,如术语聚合、范围聚合、统计聚合等。 5. **映射与分析**:了解字段映射的重要性,以及如何设置分析器进行文本分词,以满足不同的搜索...
2. **版本7.14.0的更新**:每个版本的Elasticsearch都有所改进和新功能。7.14.0可能包含了性能优化、安全增强、查询和分析算法的改进等。具体更新内容需查看官方发布文档以获取详细信息。 3. **Windows和Linux安装*...
4. 数据分析:除了搜索,Elasticsearch还具备强大的数据分析能力,可以进行聚合统计、实时分析,广泛应用于日志分析、监控系统和商业智能等领域。 5. 集群管理:在6.8.18版本中,集群管理和节点间的通信得到了...
适用于7.17.1系列,例如Elasticsearch的7.17.12版本。 elasticsearch-analysis-ik 是一个常用的中文分词器,在 Elasticsearch 中广泛应用于中文文本的分析和搜索。下面是 elasticsearch-analysis-ik 分词器的几个...
标签《ES Java API 中文文档》强调了文档的内容属性,它属于ElasticSearch的一个重要组成部分,即用Java语言进行数据交互和操作的应用程序接口部分。 从部分内容中可以提取出以下知识点: 1. **Transport Client**...