《ElasticStack从入门到实践》学习笔记7

七、ElasticSearch的聚合分析

    1.聚合分析简介

        聚合分析,英文Aggregation,是ES除了搜索功能之外提供的针对ES数据进行统计分析的功能。

        特点:①功能丰富,可满足大部分分析需求;②实时性高,所有计算结果实时返回。

#聚合分析格式:
GET my_index/_search
{
 "size":0,
 "aggs":{    #关键词
  "":{    #自定义聚合分析名称,一般起的有意义
   "":{    #聚合分析类型
    ""    #聚合分析主体
   }
  }
  [,"aggs":{[]+}]    #可包含多个子聚合分析
 }
}

        基于分析规则的不同,ES将聚合分析主要划分为以下4种:

        A、Metric。指标分析类型,如:计算最值,平均值等;

        B、Bucket。分桶类型,类似于group by语法,根据一定规则划分为若干个桶分类;

        C、Pipeline。管道分析类型,基于上一级的聚合分析结果进行再分析;

        D、Matrix。矩阵分析类型。

    2.Metric聚合分析

        主要分为两类:单值分析(输出单个结果)和多值分析(输出多个结果)。

        1)单值分析

            A、min。返回数值类型字段的最小值:

#min关键字
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "min_age":{
   "min":{    #关键字
    "field":"age"    
   }
  }
 }
}

            B、max。返回数值类型字段的最大值。

#max关键字
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "max_age":{
   "max":{    #关键字
    "field":"age"    
   }
  }
 }
}

            C、avg。返回数值类型字段的平均值。

#avg关键字
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "avg_age":{
   "avg":{    #关键字
    "field":"age"    
   }
  }
 }
}

            D、sum。返回数值类型字段值的总和。

#sum关键字
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "sum_age":{
   "sum":{    #关键字
    "field":"age"    
   }
  }
 }
}

            E、cardinality。返回字段的基数。

#cardinality关键字
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "cardinality_age":{
   "cardinality":{    #关键字
    "field":"age"    
   }
  }
 }
}

            F、使用多个单值分析关键词,返回多个结果。

#使用多个单值分析关键词,返回多个分析结果
GET my_index/_search
{
 "size": 0,
 "aggs": {
  "min_age":{
   "min":{    #求最大年龄
    "field":"age"
   }
  },
  "max_age":{
   "max":{    #求最小年龄
    "field":"age"
   }
  },
  "avg_age":{
   "avg":{    #求平均年龄
    "field":"age"
   }
  },
  "sum_age":{
   "sum":{    #求年龄总和
    "field":"age"
   }
  }
 }
}

        2)多值分析

            A、stats。返回所有单值结果:

#使用stats关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "stats_age":{
   "stats":{    #关键字
    "field":"age"    
   }
  }
 }
}

            B、extended stats。对stats进行扩展,包含更多,如:方差,标准差,标准差范围等:

#使用extended_stats关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "stats_age":{
   "extended_stats":{    #关键字
    "field":"age"    
   }
  }
 }
}

            C、Percentile。百分位数统计:

#使用percentiles关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "per_age":{
   "percentiles":{    #关键字
    "field":"age"   
   }
  }
 }
}
#使用percentiles关键词进行百分位数预测。
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "per_age":{
   "percentiles":{    #关键字
    "field":"age",
    "values":[
     20,
     25               #判断20和25分别在之前的年轻区间的什么位置,以百分数显示
    ]    
   }
  }
 }
}

            D、Top hits。一般用于分桶之后获取该桶内最匹配的定不稳当列表,即详情数据:

#使用top_hits关键词
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{
    "match":{
     "field":"job.keyword",    #按job.keyword进行分桶聚合
     "size":10
    },
    "aggs":{
     "top_employee":{
      "top_hits":{
       "size":10,    #返回文档数量
       "sort":[
        {
         "age":{
          "order":"desc"        #按年龄倒叙排列
         } 
        }
       ]
      }
     }
    }
   }
  }
 }
}

    3.Bucket聚合分析

        Bucket,意为桶。即:按照一定规则,将文档分配到不同的桶中,达分类的目的。常见的有以下五类:

        1)Terms。直接按term进行分桶,如果是text类型,按分词后的结果分桶:

#使用terms关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "terms_job":{
   "terms":{    #关键字
    "field":"job.keyword",    #按job.keyword进行分桶
    "size":5                  #返回五个文档
   }
  }
 }
}

        2)Range。按指定数值范围进行分桶:

#使用range关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "number_ranges":{
   "range":{    #关键字
    "field":"age",    #按age进行分桶
    "ranges":[
     {
      "key":">=19 && < 25",  #第一个桶:  19<=年龄<25
      "from":19,
      "to":25
     },
     {
      "key":"< 19",    #第二个桶:  年龄<19
      "to":19
     },
     {
      "key":">= 25",    #第三个桶:  年龄>=25
      "from":25
     }
    ]
   }
  }
 }
}

        3)Date Range。按指定日期范围进行分桶:

#使用date_range关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "date_ranges":{
   "date_range":{    #关键字
    "field":"birth",    #按age进行分桶
    "format":"yyyy",
    "ranges":[
     {
      "key":">=1980 && < 1990",  #第一个桶:  1980<=出生日期<1990
      "from":"1980",
      "to":"1990"
     },
     {
      "key":"< 1980",    #第二个桶:  出生日期<1980
      "to":1980
     },
     {
      "key":">= 1990",    #第三个桶:  出生日期>=1990
      "from":1990
     }
    ]
   }
  }
 }
}

        4)Histogram。直方图,按固定数值间隔策略进行数据分割:

#使用histogram关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "age_hist":{
   "histogram":{     #关键词
    "field":"age",
    "interval":3,    #设定间隔大小为2
    "extended_bounds":{    #设定数据范围
     "min":0,
     "max":30
    }
   }
  }
 }
}

        5)Date Histogram。日期直方图,按固定时间间隔进行数据分割:

#使用date_histogram关键词
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "birth_hist":{
   "date_histogram":{     #关键词
    "field":"birth",
    "interval":"year",    #设定间隔大小为年year
    "format":"yyyy",
    "extended_bounds":{    #设定数据范围
     "min":"1980",
     "max":"1990"
    }
   }
  }
 }
}

    4.Bucket+Metric聚合分析

         Bucket聚合分析允许通过添加子分析来进一步进行分析,该子分析可以是Bucket,也可以是Metric

         1)分桶之后再分桶(Bucket+Bucket),在数据可视化中一般使用千层饼图进行显示。

#分桶之后再分桶——Bucket+Bucket
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{             #第一层Bucket
    "match":{
     "field":"job.keyword",
     "size":10
    },
    "aggs":{
     "age_range":{
      "range":{             #第二层Bucket
       "field":"age",
       "ranges":[
        {"to":20},
        {"from":20,"to":30},
        {"from":30}
       ]
      }
     }
    }
   }
  }
 }
}

         2)分桶之后再数据分析(Bucket+Metric)

#分桶之后再数据分析——Bucket+Metric
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{             #第一层Bucket
    "match":{
     "field":"job.keyword",
     "size":10
    },
    "aggs":{                 
     "stats_age":{
      "stats":{            #第二层Metric
       "field":"age"
      }
     }
    }
   }
  }
 }
}

    5.Pipeline聚合分析

        针对聚合分析的结果进行再分析,且支持链式调用:

#使用pipeline聚合分析,计算订单月平均销售额。
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "sales_per_month":{
   "date_histogram":{
    "field":"date",
    "interval":"month"
   },
   "aggs":{
    "sales":{
     "sum":{
      "field":"price"
     }
    }
   }
  },
  "avg_monthly_sales":{
   "avg_bucket":{    #bucket类型
    "buckets_path":"sales_per_month>sales"    #使用buckets_path参数,表明是pipeline
   }
  }
 }
}

        pipeline的分析结果会输出到原结果中,由输出位置不同,分为两类:Parent和Sibling。

        1)Parent。结果内嵌到现有聚合分析结果中,如:Derivate、Moving Average、Cumulative Sum。

        2)Sibling。结果与现有聚合分析结果同级,如:Max/Min/Sum/Avg Bucket、Stats/Extended Stats Bucket、Percentiles Bucket。

        A、Sibling——————min_bucket,其他同理:

#Sibling聚合分析
GET my_index/_search
{
 "size": 0,
 "aggs":{
  "jobs":{
   "terms":{    #根据job.keyword进行分桶
    "field":"job.keyword",    
    "size":10
   },
   "aggs":{
    "avg_salary":{
     "avg":{    #之后Metric中求工资的平均数
      "field":"salary"
     }
    }
   }
  },
  "min_salary_by_job":{
   "min_bucket":{    #关键词
    "buckets_path":"jobs>avg_salary"    #按工资平均数,排列每个桶中的job
   }
  }
}

        B、Parent——————Derivate,其他同理:

#Parent聚合分析
GET my_index/_search
{
 "size":0,
 "aggs":{
  "bitrh":{
   "date_histogram":{
    "field":"birth",
    "interval":"year",
    "min_doc_count":0
   },
   "aggs":{
    "avg_salary":{
     "avg":{
      "field":"salary"
     }
    },
    "derivative_avg_salary":{
     "derivative":{    #关键词
      "buckets_path":"avg_salary"
     }
    }
   }
  }
 }
}

    6.聚合分析的作用范围

        ES聚合分析默认作用范围是query的结果集:

#ES中聚合分析的默认作用范围是query的结果集
GET my_index/_search
{
 "size":0,
 "query":{
  "match":{
   "username":"alfred"
  }
 },
 "aggs":{
  "jobs":{
   "terms":{
    "match":{    #此时,只在username字段中包含alfred的文档中进行分桶
     "field":"job.keyword",    
     "size":10
    }
   }
  }
 }
}

        可通过以下方式修改:

            ①filter。

            ②post_filter。

            ③global。

        1)filter,为某个结合分析设定过滤条件,从而在不改变整体query语句的情况下修改范围。

#使用filter进行过滤
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs_salary_small":{
   "filter":{
    "range":{
     "salary":{
      "to":10000
     }
    }
   },
   "aggs":{
    "jobs":{
     "terms":{    #在salary小于10000的文档中对工作进行分桶
      "field":"job.keyword"
     }
    }
   }
  }
 }
}

        2)post_filter,作用于文档过滤,但在聚合分析之后才生效。

#使用post_filter进行过滤
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{    #在salary小于10000的文档中对工作进行分桶
    "field":"job.keyword"
   }
  }
 },
 "post_filter":{    #在集合分析之后才生效
  "match":{
   "job.keyword":"java engineer"   
  }
 }
}

        3)global,无视query条件,基于所有文档进行分析。

#使用global进行过滤
GET my_index/_search
{
 "query":{
  "match":{
   "job.keyword":"java engineer"
  }
 },
 "aggs":{
  "java_avg_salary":{
   "avg":{
    "field":"salary"
   }
  },
  "all":{
   "global":{    #关键词
    "aggs":{
     "avg_salary":{
      "avg":{
       "field":"salary"    #依然是对所有的文档进行查询,而不会去管query   
      }
     }
    }
   }
  }
 }
}

    7.聚合分析中的排序

        1)可使用自带的关键数据排序,如:

            _count 文档数、_key按key值

#使用自带的数据进行排序
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{
    "field":"job.keyword",
    "size":10,
    "order":[
    {
     "_count":"asc"    #默认按_count倒叙排列
    },
    {
     "_key":"desc"    使用多个排序值,从上往下的顺序进行排列
    }
    ]
   }
  }
 }
} 

        1)也可使用聚合结果进行排序,如:

#使用聚合结果进行排序
GET my_index/_search
{
 "size":0,
 "aggs":{
  "salary_hist":{
   "histogram":{
   },
   "aggs":{
    "age":{
     "filter":{
      "range":{
       "age":{
        "gte":10
       }
      }
     },
     "aggs":{
      "avg_age":{
       "field":"age"
      }
     } 
    }
   }
  }
 }
}

    8.计算精准度

        每个Shard上分别计算,由coordinating Node做聚合,多个Shard上分散着若干数据,而coordinating Node无法得知,那么在取数据的时候,比如:top hits的时候,结果有偏差,造成精准度不准确。解决办法有两种:

        1)直接设置shard数量为1;

        2)设置shard_size大小,即每次从shard上额外多获取数据,从而提升精准度

#使用shard_size额外获取数据
GET my_index/_search
{
 "size":0,
 "aggs":{
  "jobs":{
   "terms":{
    "field":"job.keyword",
    "size":1,
    "shard_size":10    
   }
  }
 }
}

        terms返回聚合结果中有两个统计值:

        

        doc_count_error_upper_bound:被一楼的term可能的最大值;

        sum_other_doc_count:返回结果bucket的term外其他term的文档总数。

《ElasticStack从入门到实践》学习笔记7_第1张图片

        三者只能取其二。

你可能感兴趣的:(大数据相关,ElasticStack,数据分析,搜索引擎)