栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Elasticsearch系列---聚合查询(一)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Elasticsearch系列---聚合查询(一)

概要

Elasticsearch的聚合查询,跟数据库的聚合查询效果是一样的,我们可以将二者拿来对比学习,如求和、求平均值、求最大最小等等。

基础概念 bucket

数据分组,一些数据按照某个字段进行bucket划分,这个字段值相同的数据放到一个bucket中。可以理解成Java中的Map结构,类似于Mysql中的group by后的查询结果。

metric:

对一个数据分组执行的统计,比如计算最大值,最小值,平均值等
类似于Mysql中的max(),min(),avg()函数的值,都是在group by后使用的。

案例

我们还是以英文儿歌为案例背景,回顾一下索引结构:

PUT /music
{
  "mappings": {
      "children": {
 "properties": {
   "id": {
     "type": "keyword"
   },
   "author_first_name": {
     "type": "text",
     "analyzer": "english"
   },
   "author_last_name": {
     "type": "text",
     "analyzer": "english"
   },
   "author": {
     "type": "text",
     "analyzer": "english",
     "fields": {
"keyword": {
  "type": "keyword",
  "ignore_above": 256
}
     }
   },
   "name": {
     "type": "text",
     "fields": {
"keyword": {
  "type": "keyword",
  "ignore_above": 256
}
     }
   },
   "content": {
     "type": "text",
     "fields": {
"keyword": {
  "type": "keyword",
  "ignore_above": 256
}
     }
   },
   "language": {
     "type": "text",
     "analyzer": "english",
     "fielddata": true
   },
   "tags": {
     "type": "text",
     "analyzer": "english"
   },
   "length": {
     "type": "long"
   },
   "likes": {
     "type": "long"
   },
   "isRelease": {
     "type": "boolean"
   },
   "releaseDate": {
     "type": "date"
   }
 }
      }
  }
}
统计目前收录的哪种语言的歌曲最多
GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "song_qty_by_language": {
      "terms": {
 "field": "language"
      }
    }
  }
}

语法解释:

  • size:0 表示只要统计后的结果,原始数据不展现
  • aggs:固定语法 ,聚合分析都要声明aggs
  • song_qty_by_language:聚合的名称,可以随便写,建议规范命名
  • terms:按什么字段进行分组
  • field:具体的字段名称

响应结果如下:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 5,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "song_qty_by_language": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
 {
   "key": "english",
   "doc_count": 5
 }
      ]
    }
  }
}

语法解释:

  • hits: 由于请求时设置了size:0,hits就是空的
  • aggregations:聚合查询的结果
  • song_qty_by_language:请求时声明的名称
  • buckets:根据指定字段查询后得到的数据分组集合,[]内的是每一个数据分组,其中key为每个bucket的对应指定字段的值,doc_count为统计的数量。

默认按doc_count降序排序。

按语种统计每种歌曲的平均时长
GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "lang": {
      "terms": {
 "field": "language"
      },
      "aggs": {
 "length_avg": {
   "avg": {
     "field": "length"
   }
 }
      }
    }
  }
}

这里演示的是两层aggs聚合查询,先按语种统计,得到数据分组,再在数据分组里算平均时长。

多个aggs嵌套语法也是如此,注意一下aggs代码块的位置即可。

统计最长时长、最短时长等的歌曲

最常用的统计:count,avg,max,min,sum,语法含义与mysql相同。

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "color": {
      "terms": {
 "field": "language"
      },
      "aggs": {
 "length_avg": {
   "avg": {
     "field": "length"
   }
 },
 "length_max": {
   "max": {
     "field": "length"
   }
 },
 "length_min": {
   "min": {
     "field": "length"
   }
 },
 "length_sum": {
   "sum": {
     "field": "length"
   }
 }
      }
    }
  }
}
按时长分段统计歌曲平均时长

以30秒为一段,看各段区间的平均值。

histogram语法位置跟terms一样,作范围分区,搭配interval参数一起使用
interval:30表示分的区间段为[0,30),[30,60),[60,90),[90,120)

段的闭合关系是左开右闭,如果数据在某段区间内没有,也会返回空的区间。

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "sales_price_range": {
      "histogram": {
 "field": "length",
 "interval": 30
      },
      "aggs": {
 "length_avg": {
   "avg": {
     "field": "length"
   }
 }
      }
    }
  }
}

这种数据的结果可以用来生成柱状图或折线图。

按上架日期分段统计新歌数量

按月统计

date histogram与histogram语法类似,搭配date interval指定区间间隔
extended_bounds表示最大的时间范围。

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "sales": {
      "date_histogram": {
 "field": "releaseDate",
 "interval": "month",
 "format": "yyyy-MM-dd",
 "min_doc_count": 0,
 "extended_bounds": {
   "min": "2019-10-01",
   "max": "2019-12-31"
 }
      }
    }
  }
}

interval的值可以天、周、月、季度、年等。我们可以延伸一下,比如统计今年每个季度的新发布歌曲的点赞数量

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "sales": {
      "date_histogram": {
 "field": "releaseDate",
 "interval": "quarter",
 "format": "yyyy-MM-dd",
 "min_doc_count": 0,
 "extended_bounds": {
   "min": "2019-01-01",
   "max": "2019-12-31"
 }
      },
      "aggs": {
 "lang_qty": {
   "terms": {
     "field": "language"
   },
   "aggs": {
     "like_sum": {
"sum": {
  "field": "likes"
}
     }
   }
 },
 "total" :{
   "sum": {
     "field": "likes"
   }
 }
      }
    }
  }
}
带上过滤条件

聚合查询可以和query搭配使用,相当于mysql中where与group by联合使用

查询条件
GET /music/children/_search
{
  "size": 0,
  "query": {
    "match": {
      "language": "english"
    }
  },
  "aggs": {
    "sales": {
      "terms": {
 "field": "language"
      }
    }
  }
}
过滤条件
GET /music/children/_search
{
  "size": 0,
  "query": {
    "constant_score": {
      "filter": {
 "term": {
   "language": "english"
 }
      }
    }
  },
  "aggs": {
    "sales": {
      "terms": {
 "field": "language"
      }
    }
  }
}
global bucket查询

global:就是global bucket,会将所有的数据纳入聚合scope,不受前面的query或filter影响。

global bucket适用于同时统计指定条件的数据与全部数据的对比,如我们创造的场景:指定作者的歌与全部歌曲的点赞数量对比。

GET /music/children/_search
{
  "size": 0,
  "query": {
    "match": {
      "author": "Jean Ritchie"
    }
  },
  "aggs": {
    "likes": {
      "sum": {
 "field": "likes"
      }
    },
    "all": {
      "global": {},
      "aggs": {
 "all_likes": {
   "sum": {
     "field": "likes"
   }
 }
      }
    }
  }
}
统计近2月,近1月的点赞数

aggs.filter针对是聚合里的数据

bucket filter:对不同的bucket下的aggs,进行filter

类似于mysql的中having语法

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "recent_60d": {
      "filter": {
 "range": {
   "releaseDate": {
     "gte": "now-60d"
   }
 }
      },
      "aggs": {
 "recent_60d_likes_sum": {
   "sum": {
     "field": "likes"
   }
 }
      }
    },
    "recent_30d": {
      "filter": {
 "range": {
   "releaseDate": {
     "gte": "now-30d"
   }
 }
      },
      "aggs": {
 "recent_30d_likes_sum": {
   "avg": {
     "field": "likes"
   }
 }
      }
    }
  }
}
统计排序

默认按doc_count降序排序,排序规则可以改,order里面可以指定aggs的别名,如length_avg,类似于mysql的order by cnt asc。

GET /music/children/_search
{
  "size": 0,
  "aggs": {
    "group_by_lang": {
      "terms": {
 "field": "language",
 "order": {
   "length_avg": "desc"
 }
      },
      "aggs": {
 "length_avg": {
   "avg": {
     "field": "length"
   }
 }
      }
    }
  }
}
小结

本篇主要介绍常用的聚合查询,均以示例为主,了解基本写法后可以快速阅读,有不好理解的地方,多与我们熟悉的数据库查询SQL作比较,谢谢。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号