学习 ES(elasticsearch)搜索引擎 2 --- 聚合进阶

二、Elasticsearch进阶篇

2.1 Elasitcsearch数据同步

    2.1.1 ES与关系型数据库同步

    2.1.2 ES与非关系型数据库同步

    2.1.3 ES与Kafka同步

    2.1.4 ES文件同步

    2.1.5 ES同步小结

 

2.2 Elasticsearch检索进阶

2.3 Elasitcsearch聚合进阶

    39、 Elasticsearch聚合深入详解——对比Mysql实现

【参考: https://blog.csdn.net/laoyang360/article/details/79048455 】

聚合认知前提
    桶(Buckets)  ——满足特定条件的文档的集合 
    指标(Metrics)——对桶内的文档进行统计计算

    SELECT COUNT(color)  FROM table  GROUP BY color

        COUNT(color) 相当于指标。 
        GROUP BY color 相当于桶。

è¿éåå¾çæè¿°

一、聚合起步

1、创建索引

1.1 创建索引DSL实现

put cars
POST /cars/transactions/_bulk
{ "index": {}}
{ "price" : 10000, "color" : "red", "make" : "honda", "sold" : "2014-10-28" }
{ "index": {}}
{ "price" : 20000, "color" : "red", "make" : "honda", "sold" : "2014-11-05" }
{ "index": {}}
{ "price" : 30000, "color" : "green", "make" : "ford", "sold" : "2014-05-18" }
{ "index": {}}
{ "price" : 15000, "color" : "blue", "make" : "toyota", "sold" : "2014-07-02" }

1.2 创建mysql库表sql实现

CREATE TABLE `cars` (
  `id` int(11) NOT NULL,
  `price` int(11) DEFAULT NULL,
  `color` varchar(255) DEFAULT NULL,
  `make` varchar(255) DEFAULT NULL,
  `sold` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

2、统计不同颜色车的数目

2.1 统计不同颜色车的DSL实现【ES】 

GET /cars/transactions/_search
{
  "size":0,
  "aggs":{
      "popular_colors" : {
          "terms":{
              "field": "color.keyword"
           }
       }
   }
}

过滤条件: 
聚合条件
aggs:颜色 Color; 【相当于group by
排序条件:

返回结果:lve

2.2 统计不同颜色的mysql实现

select color, count(color) as cnt from cars group by color order by cnt desc;

返回结果:

red 4
green 2
blue 2

 

3、统计不同颜色车的平均价格

3.1 统计不同颜色车的平均价格DSL实现:aggs -- avg_price -- avg -- "field": "price"

3.2 统计不同颜色车的平均价格sql实现:

select 
    color, 
    count(color) as cnt, 
    avg(price) as avg_price 
from cars group by color order by cnt desc;

返回结果:
     color   cnt      avg_price
     red       4      32500.0000
     green   2      21000.0000
     blue     2      20000.0000

 

4、每种颜色汽车制造商的分布

4.1 统计每种颜色汽车制造商的分布dsl实现: aggs -- colors;aggs -- make。

4.2 统计每种颜色汽车制造商的分布sql实现

select color, make from cars order by color;

说明:和dsl的实现不严格对应

     color make

     blue toyota

     blue ford

     green ford

     green toyota

     red honda

     red honda

5、统计每个制造商的最低价格、最高价格

5.1 统计每个制造商的最低、最高价格的DSL实现

5.2 统计每个制造商的最低、最高价格的sql实现

select
    make, 
    min(price) as min_price, 
    max(price) as max_price 
from cars 
group by make;

          make       min_price        max_price
          bmw        80000                80000
          ford         25000                30000
          honda     10000                20000
          toyota     12000                15000

 

二、聚合进阶

1、条形图聚合

1.1 分段统计每个区间的汽车销售价格总和

GET /cars/transactions/_search
{
  "size":0,
  "aggs":{
      "price" : {
          "histogram":{
              "field": "price",
              "interval": 20000
          },
          "aggs":{
              "revenue":{
                  "sum":{
                      "field": "price"
                  }
              }
          }
      }
  }
}

过滤条件: 价格区间
聚合条件
aggs:价格总和; 【相当于group by
排序条件:

汽车销售价格区间:定义为20000; 
分段统计price和用sum统计。

1.2 多维度度量不同制造商的汽车指标

GET /cars/transactions/_search
{
  "size" : 0,
  "aggs": {
      "makes": {
          "terms": {
              "field": "make.keyword",
              "size": 10
          },
          "aggs": {
              "stats": {
                  "extended_stats": {
                      "field": "price"
                  }
               }
          }
      }
  }
}

 

2、按时间统计聚合

2.1 按月份统计制造商汽车销量dsl实现

2.2 按月份统计制造商汽车销量sql实现

SELECT 
    make, 
    count(make) as cnt, 
    CONCAT(YEAR(sold),  ',',  MONTH(sold)) AS data_time
FROM `cars`
GROUP BY YEAR(sold) DESC,MONTH(sold)

查询结果如下:
       make      cnt        data_time
       bmw        1               2014,1
       ford         1               2014,2
       ford         1               2014,5
       toyota     1               2014,7
       toyota     1               2014,8
       honda     1               2014,10
       honda     2               2014,11

 

2.3 包含12月份的处理DSL实现

以上2.1 中没有12月份的统计结果显示。

2.4 以季度为单位统计DSL实现

 

 

2.5 基于搜索的(范围限定)聚合操作

2.5.1 基础查询聚合

GET /cars/transactions/_search
{
  "query" : {
      "match" : {
          "make.keyword" : "ford"
      }
  },
  "aggs" : {
      "colors" : {
          "terms" : {
              "field" : "color.keyword"
          }
      }
  }
}

对应的sql实现:

select 
    make, color 
from cars
where make = "ford";

结果返回如下: make      color

                          ford         green

                         ford         blue

 

三、过滤聚合

1. 过滤操作

统计全部汽车的平均价钱以及单品平均价钱;

select avg(price) from cars;

select make, color, avg(price) from cars
where make = "ford" ;

 

2、范围限定过滤(过滤桶)

我们可以指定一个过滤桶,当文档满足过滤桶的条件时,我们将其加入到桶内。

mysql的实现如下:

select *, avg(price) 
from cars 
where period_diff(date_format(now() , '%Y%m') , date_format(sold, '%Y%m')) > 30
and make = "ford";

mysql查询结果如下:

              id         price        color        make        sold                avg

             3           30000      green       ford        2014-05-18      27500.0000

3、后过滤器

只过滤搜索结果,不过滤聚合结果——post_filter实现

GET /cars/transactions/_search
{
  "query": {
      "match": {
          "make": "ford"
      }
   },
  "post_filter": {
      "term" : {
          "color.keyword" : "green"
      }
  },
  "aggs" : {
      "all_colors": {
          "terms" : { "field" : "color.keyword" }
      }
  }
}

post_filter 会过滤搜索结果,只展示绿色 ford 汽车。这在查询执行过 后 发生,所以聚合不受影响。

 

小结 
选择合适类型的过滤(如:搜索命中、聚合或两者兼有)通常和我们期望如何表现用户交互有关。

选择合适的过滤器(或组合)取决于我们期望如何将结果呈现给用户。

在 filter 过滤中的 non-scoring 查询,同时影响搜索结果和聚合结果。
filter 桶影响聚合。
post_filter 只影响搜索结果。

 

四、多桶排序

4.1 内置排序 -- order

4.2 按照度量排序

以下是按照汽车平均售价的升序进行排序。 
过滤条件:汽车颜色; 
聚合条件:平均价格; 
排序条件:汽车的平均价格升序。

GET /cars/transactions/_search
{
  "size" : 0,
  "aggs" : {
      "colors" : {
          "terms" : {
              "field" : "color.keyword",
              "order": {
                  "avg_price" : "asc"
               }
           },
          "aggs": {
              "avg_price": {
                  "avg": {"field": "price"}
               }
           }
      }
    }
}

 

4.3 基于“深度”的度量排序

太复杂,不推荐!

五、近似聚合

cardinality的含义是“基数”;

5.1 统计去重后的数量

类似于:

SELECT COUNT(DISTINCT color)  FROM cars;

六、doc values解读

 

 

Elasticsearch聚合后分页深入详解

https://blog.csdn.net/laoyang360/article/details/79112946

1、Elasticsearch支持聚合后分页吗,为什么?

不支持,看看Elasticsearch员工如何解读。 

 

2、Elasticsearch要实现聚合后分页,该怎么办?

方案:需要展示满足条件的全部数据条数,即需要全量聚合,且按照某规则排序。 
记住,如果数据基数大(十万、百万甚至千万级),这必然会很慢。

步骤1:全量聚合,size设置为: 2147483647。 
ES5.X/6.X版本设置为2147483647 ,它等于2^31-1, 
是32位操作系统中最大的符号型整型常量;ES1.X 2.X版本设置为0。

步骤2:将聚合结果存入内存中,可以考虑list或map存储。 
这里存入list的_id是基于某种规则排序过的,如:基于插入时间。

步骤3:内存内分页,基于list中存储值结合偏移值进行筛选。 
如每页10条数据,取第一页就是:取list中第0到第9个元素,以此类推。

步骤4:基于筛选出的值进行二次查询获取详情。 
此处的筛选条件已经能唯一确定一篇document。

 

3、“聚合后不能分页,但能分区来取”,是什么鬼?

貌似,没有起到分页的作用。此处没有深入研究。

 

4、聚合后分页实战

步骤1:建立索引 

put book_index

步骤2:导入数据

举例原因,假设后来导入百万甚至千万级别数据。

POST book_index/book_type/1

步骤3:聚合

要求:按照以下条件聚合 
1)相同作者出书量;(聚合) 
2)相同作者的书,取时间最大的返回。(聚合后排序)

步骤4:获取关键信息存入list。

步骤5:二次遍历+偏移截取分页实现。

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值