文章目录

  • 什么是聚合操作?(MySQL)
  • 1.聚合函数
  • 2.聚合分组
  • 3.聚合筛选
  • 为什么不能在where语句中使用聚合函数,与having的区别?
  • ES的聚合查询(在Kibana中的原生操作)
  • 1.聚合查询简介
  • elasticsearch聚合--桶(Buckets)和指标(Metrics)的概念
  • [3. 如何运行一个聚合查询]()
  • 4. [ElasticSearch聚合查询报错:Text fields are not optimised for operations that require per-document field data(报错原因:需要聚合的字段不支持聚合或排序--比如,字段类型是text就不支持聚合排序)]()
  • 5. [对于字段类型是text不支持聚合查询的解决办法]()
  • RestHighLevelClient的聚合查询API使用
  • 最后附一个某个大佬的ES的API详解中文版



申明:本文是在实现ES聚合功能中,将过程中查找的多篇博客文献拼接在一起,参考到的博文全部在标题中附上了原文的超链接,分享出来仅是为了提做一个笔记以防忘记,并给大家提供一个参考。

什么是聚合操作?(MySQL)

聚合操作指的是在数据查找基础上对于数据进一步整理筛选行为,聚合操作也属于护具的查询筛选范围。

1.聚合函数

方法

功能

avg(字段名)

该字段的平均值

max(字段名)

该字段的最大值

min(字段名)

该字段的最小值

sum(字段名)

该字段所有记录的和

count(字段名)

统计该字段的记录个数

eg1 : 找出表中的最大攻击力国家的值?

select max(attack) from countries;

注意: 此时select 后只能写聚合函数,无法查找其他字段,除非该字段值全都一样。(否则写了其他的属性,其他字段只返回那个字段的第一行数据。)

2.聚合分组

group by
给查询的结果分组
e.g. : 计算每个国家的平均攻击力

select country,avg(attack) from countries group by country;

3.聚合筛选

having语句
对分组聚合后的结果进行进一步筛选

eg1 : 找出平均攻击力大于105的国家的前2名,显示国家名称和平均攻击力
select country,avg(attack) from countries group by country having avg(attack) > 105 order by avg(attack) desc limit 2;

注意

  1. having语句必须与group by联用2.
  2. having语句存在弥补了where关键字不能与聚合函数联合使用的不足,where只能操纵表中实际存在的字段。 (意思是where关键中不能出现max(value)、count(country)这类的聚合函数)
    第2条"where关键字不能与聚合函数联合使用"原因见下

为什么不能在where语句中使用聚合函数,与having的区别?

SQL语句的执行顺序

第一步:from 选择表

第二步:where 筛选条件,筛选对象–行

第三步:group by 将筛选出来的数据进行分组

第四步:having 筛选条件,筛选对象–组

第五步:select 选取最后的结果

第六步:order by 将结果按照特定顺序排列

聚合函数是针对结果集的,但是where条件并不是在查询出结果集之后运行的,所以“聚合函数”不能放在where条件中;
而因为having是对于结果集进行分组,所以聚合函数可以放在having中。

ES的聚合查询(在Kibana中的原生操作)

1.聚合查询简介

聚合查询可以将数据汇总为度量、统计或其他分析。

聚合查询主要分为三个类别:

  • Metric 指标聚合
  • Bucket 桶聚合
  • Pipeline 管道聚合

elasticsearch聚合–桶(Buckets)和指标(Metrics)的概念

在Elasticsearch的聚合中需要掌握两个核心的概念:桶(bucket)、指标(metric)

桶(bucket): 满足特定条件的文档的集合

指标(metric): 对桶内的文档进行聚合分析的操作

(ps:每个聚合都是一个或者多个桶和零个或者多个指标的组合。)

翻译成粗略的SQL语句来解释的话:

SELECT COUNT(color)  —> 相当于指标

FROM table

GROUP BY color  —>2  相当于桶

桶在概念上类似于SQL的分组(GROUP BY),而指标则类似于COUNT()、SUM()、MAX()等统计方法。

3. 如何运行一个聚合查询

GET /my-index-000001/_search
{
  "aggs": {
    "my-agg-name": {
      "terms": {
        "field": "my-field"
      }
    }
  }
}

说明:
aggs 说明采用的是聚合查询
my-agg-name 是聚合查询的名称
terms 说明采用的是Terms aggregation多值聚合:一个基于多桶值源的聚合,其中桶是动态构建的——每个唯一值一个桶。统计每个唯一值的个数。
field 指定需要统计的字段。

4. ElasticSearch聚合查询报错:Text fields are not optimised for operations that require per-document field data(报错原因:需要聚合的字段不支持聚合或排序–比如,字段类型是text就不支持聚合排序)

5. 对于字段类型是text不支持聚合查询的解决办法

对于text类型字段,fields中添加一个keyword,以及fields相关的属性详解,官网教程

官网对于fields属性作用的中文翻译:fields字段经常使用于用于不同目的索引相同字段。这是使用多字段的目的。举个例子,一个字符串类型能够被映射成text类型方便全文搜索,同时他也可以在排序或者聚合查询时被当做keyword类型。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",
        "fields": {
          "keyword": { 
            "type":  "keyword"
          }
        }
      }
    }
  }
}

在已经构建了索引,想要在原索引的text字段的fields属性上再添加一个keyword多字段 1.查看索引类型结构

GET /my_index/_mapping
查询结果: { “my_index” : {
 “mappings” : {
 “_meta” : { },
 “_source” : {
 “includes” : [ ],
 “excludes” : [ ]
 }
 “numeric_detection” : false,
 “properties” : {
 …
 “my_field” : {
 “type” : “text”
 } } }


2.添加keyword类型

PUT /my_index/_mapping
{
  "properties": {
      "my_field": {
      "type": "text",
      "fields":{
        "keyword":{
          "type":"keyword",
          "ignore_above":256
        }
      }
    }
  }
}

但是在已经构建了索引,想要在原索引的text字段的fields属性上再添加一个keyword多字段。在添加之前的数据还是无法进行“聚合”、“排序”操作,只有在添加了多字段后的数据才可以被“聚合”、“排序”。

RestHighLevelClient的聚合查询API使用

import org.elasticsearch.client.RestHighLevelClient;
@Autowired
RestHighLevelClient restHighLevelClient;//把RestHighLevelClient放入spring容器中管理
//1、创建查询请求对象
SearchRequest searchRequest = new SearchRequest("参数是es索引名");
//2、创建搜索条件 builder对象  加入大多数搜索参数,提供在search中的request body的设置
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
//3、创建聚合查询对象
TermsAggregationBuilder aggBuilder = 
AggregationBuilders.terms("参数是聚合查询的builder对象名")                
.field("参数是es索引库中的聚合查询字段名")
// 第1个(terms)中的参数名字可以随意取,但是后面用到的时候名字要一一对应
// 第2个(field)中的参数与es库中的聚合查询字段名要完全一致

//4、将聚合查询搜索条件放入Builder对象
searchSourceBuilder.aggregation(aggBuilder);
//5、将条件Builder对象放入searchRequest查询对象之中
searchRequest.source(searchSourceBuilder);
//6、client客户端执行查询,并返回SearchResponse类型的返回结果
SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//7.聚合查询 的结果返回
Aggregations aggregations = response.getAggregations();
//8.标记对应分组名,以及该分组的数量
Map<String,Long> group = new HashMap<>();
for (Terms.Bucket bucket : aggregation.getBuckets()) {//这个是每种查询条件下 结果分类循环
//bucket.getKeyAsString() 查到的对应分组类型名
//bucket.getDocCount() 查询到的对应分组对应的数量
	group.put(bucket.getKeyAsString(),bucket.getDocCount());
}

最后附一个某个大佬的ES的API详解中文版

包括:javaHighLevelRestClient版本的,以及Transport client版本的