赞
踩
Elasticsearch除搜索以外,提供了针对ES 数据进行统计分析的功能。聚合(aggregations)可以让我们极其方便的实现对数据的统计、分析、运算。例如:
聚合查询可以用于各种场景,比如商业智能、数据挖掘、日志分析等等。
聚合查询的语法结构与其他查询相似,通常包含以下部分:
- GET <index_name>/_search
- {
- "aggs": {
- "<aggs_name>": { // 聚合名称需要自己定义
- "<agg_type>": {
- "field": "<field_name>"
- }
- }
- }
- }
- #创建索引库
- PUT /employees
- {
- "mappings": {
- "properties": {
- "age":{
- "type": "integer"
- },
- "gender":{
- "type": "keyword"
- },
- "job":{
- "type" : "text",
- "fields" : {
- "keyword" : {
- "type" : "keyword",
- "ignore_above" : 50
- }
- }
- },
- "name":{
- "type": "keyword"
- },
- "salary":{
- "type": "integer"
- }
- }
- }
- }
-
- PUT /employees/_bulk
- { "index" : { "_id" : "1" } }
- { "name" : "Emma","age":32,"job":"Product Manager","gender":"female","salary":35000 }
- { "index" : { "_id" : "2" } }
- { "name" : "Underwood","age":41,"job":"Dev Manager","gender":"male","salary": 50000}
- { "index" : { "_id" : "3" } }
- { "name" : "Tran","age":25,"job":"Web Designer","gender":"male","salary":18000 }
- { "index" : { "_id" : "4" } }
- { "name" : "Rivera","age":26,"job":"Web Designer","gender":"female","salary": 22000}
- { "index" : { "_id" : "5" } }
- { "name" : "Rose","age":25,"job":"QA","gender":"female","salary":18000 }
- { "index" : { "_id" : "6" } }
- { "name" : "Lucy","age":31,"job":"QA","gender":"female","salary": 25000}
- { "index" : { "_id" : "7" } }
- { "name" : "Byrd","age":27,"job":"QA","gender":"male","salary":20000 }
- { "index" : { "_id" : "8" } }
- { "name" : "Foster","age":27,"job":"Java Programmer","gender":"male","salary": 20000}
- { "index" : { "_id" : "9" } }
- { "name" : "Gregory","age":32,"job":"Java Programmer","gender":"male","salary":22000 }
- { "index" : { "_id" : "10" } }
- { "name" : "Bryant","age":20,"job":"Java Programmer","gender":"male","salary": 9000}
- { "index" : { "_id" : "11" } }
- { "name" : "Jenny","age":36,"job":"Java Programmer","gender":"female","salary":38000 }
- { "index" : { "_id" : "12" } }
- { "name" : "Mcdonald","age":31,"job":"Java Programmer","gender":"male","salary": 32000}
- { "index" : { "_id" : "13" } }
- { "name" : "Jonthna","age":30,"job":"Java Programmer","gender":"female","salary":30000 }
- { "index" : { "_id" : "14" } }
- { "name" : "Marshall","age":32,"job":"Javascript Programmer","gender":"male","salary": 25000}
- { "index" : { "_id" : "15" } }
- { "name" : "King","age":33,"job":"Java Programmer","gender":"male","salary":28000 }
- { "index" : { "_id" : "16" } }
- { "name" : "Mccarthy","age":21,"job":"Javascript Programmer","gender":"male","salary": 16000}
- { "index" : { "_id" : "17" } }
- { "name" : "Goodwin","age":25,"job":"Javascript Programmer","gender":"male","salary": 16000}
- { "index" : { "_id" : "18" } }
- { "name" : "Catherine","age":29,"job":"Javascript Programmer","gender":"female","salary": 20000}
- { "index" : { "_id" : "19" } }
- { "name" : "Boone","age":30,"job":"DBA","gender":"male","salary": 30000}
- { "index" : { "_id" : "20" } }
- { "name" : "Kathy","age":29,"job":"DBA","gender":"female","salary": 20000}
—些数学运算,可以对文档字段进行统计分析,类比Mysql中的 min(), max(), sum() 操作。
- POST /employees/_search
- {
- "aggs": {
- "max_salary": {
- "max": {
- "field": "salary"
- }
- },
- "min_salary": {
- "min": {
- "field": "salary"
- }
- },
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- }
注意查询的时候如果不加 size = 0 会查询出来默认的 10 条数据
如果不想要数据只想要统计结果,可以加上 size = 0
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "max_salary": {
- "max": {
- "field": "salary"
- }
- },
- "min_salary": {
- "min": {
- "field": "salary"
- }
- },
- "avg_salary": {
- "avg": {
- "field": "salary"
- }
- }
- }
- }
stats 可以输出多个统计值
- POST /employees/_search
- { "size": 0,
- "aggs": {
- "stats_salary": {
- "stats": {
- "field": "salary"
- }
- }
- }
- }
cardinate 对搜索结果去重
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "cardinate": {
- "cardinality": {
- "field": "job"
- }
- }
- }
- }
这里需要注意:如果需要计算的字段是 text 类型,会报错
解决方案有两种:
方案一、开启 fielddata :
然后就可以对 job 进行聚合计算了
但需要注意的是:
text
字段启用 fielddata
可能会导致大量的内存使用,这可能会影响到集群的性能和稳定性。fielddata
可能会降低查询性能。
可以看到上面示例,分类的指标都是分词后的结果
下面的示例也是一样的,统计的值也是分词后的结果
这里可以看到 分词后分类有 10 条数,但是使用 keyword 只有 7 条数据
原因就是,fielddata 对先分词 再对分词进行分类计算
- PUT /employees/_mapping
- {
- "properties" : {
- "job":{
- "type": "text",
- "fielddata": true
- }
- }
- }
-
- # 对 Text 字段进行分词,分词后的terms
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job"
- }
- }
- }
- }
方案二、keyword类型
如果你的目的是对某个字段进行排序或聚合,但不需要全文搜索,那么考虑使用 keyword
类型而不是 text
类型可能是一个更好的选择。keyword
类型默认启用 fielddata
,并更适合此类操作。
上面这个示例 keyword 不会对字段的值进行分词,统计值 7 条数据
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "cardinate": {
- "cardinality": {
- "field": "job.keyword"
- }
- }
- }
- }
按照一定的规则,将文档分配到不同的桶中,从而达到分类的目的。ES提供的一些常见的 Bucket Aggregation。
桶聚合可以用于各种场景,例如:
获取job的分类信息
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword"
- }
- }
- }
- }
聚合可配置属性有:
默认情况下,Bucket聚合会统计Bucket内的文档数量,记为_count,并且按照_count降序排序。我们可以指定order属性,自定义聚合的排序方式:
- GET /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword",
- "size": 10,
- "order": {
- "_count": "asc"
- }
- }
- }
- }
- }
只对 salary 20000 以上的进行聚合
- #限制聚合范围
- POST /employees/_search
- {
- "query": {
- "range": {
- "salary": {
- "gte": 20000
- }
- }
- },
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field": "job.keyword",
- "size": 10,
- "order": {
- "_count": "asc"
- }
- }
- }
- }
- }
自定义范围对 salary 分桶
- #Salary Range分桶,可以自己定义 key
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "salary_range": {
- "range": {
- "field":"salary",
- "ranges":[
- {
- "to":10000
- },
- {
- "from":10000,
- "to":20000
- },
- {
- "key":">20000",
- "from":20000
- }
- ]
- }
- }
- }
- }
以 salary 5000 为间隔进行分桶
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "salary_histrogram": {
- "histogram": {
- "field": "salary",
- "interval": 5000
- }
- }
- }
- }
也可以指定范围:
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "salary_histrogram": {
- "histogram": {
- "field": "salary",
- "interval": 5000,
- "extended_bounds": {
- "min": 0,
- "max": 60000
- }
- }
- }
- }
- }
但是这种方式指定范围,好像默认也会输出到最大的那个桶,
我这里指定最大是 10000 但是也会把索引中最大的值输出,
既然默认都会输出最大值,那么指定超过最大值的数值,后面都是 0 也没有统计的必要了
这里感兴趣的小伙伴可以研究一下~
然后如果需要对指定范围的薪资进行统计,可以使用 range query
这样就只统计 20000 以内的数据了
- POST /employees/_search
- {
- "query": {
- "range": {
- "salary": {
- "gte": 0,
- "lte": 20000
- }
- }
- },
- "size": 0
- , "aggs": {
- "salary_histrogram": {
- "histogram": {
- "field": "salary",
- "interval": 5000
- }
- }
- }
- }
top_hits
应用场景: 当获取分桶后,桶内最匹配的顶部文档列表
比如:不同工种中,年纪最大的3个员工的具体信息
- POST /employees/_search
- {
- "size": 0,
- "aggs": {
- "jobs": {
- "terms": {
- "field":"job.keyword"
- },
- "aggs":{
- "old_employee":{
- "top_hits":{
- "size":3,
- "sort":[
- {
- "age":{
- "order":"desc"
- }
- }
- ]
- }
- }
- }
- }
- }
- }
嵌套聚合
按照工作类型分桶,并统计工资信息
- # 嵌套聚合1,按照工作类型分桶,并统计工资信息
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "Job_salary_stats": {
- "terms": {
- "field": "job.keyword"
- },
- "aggs": {
- "salary": {
- "stats": {
- "field": "salary"
- }
- }
- }
- }
- }
- }
根据工作类型分桶,然后按照性别分桶,计算工资的统计信息
- # 多次嵌套。根据工作类型分桶,然后按照性别分桶,计算工资的统计信息
- POST employees/_search
- {
- "size": 0,
- "aggs": {
- "Job_gender_stats": {
- "terms": {
- "field": "job.keyword"
- },
- "aggs": {
- "gender_stats": {
- "terms": {
- "field": "gender"
- },
- "aggs": {
- "salary_stats": {
- "stats": {
- "field": "salary"
- }
- }
- }
- }
- }
- }
- }
- }
感谢观看!!!感兴趣的小伙伴可以关注收藏,持续更新中~~~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。