# 创建索引
PUT /hotel
{
"settings": {
"number_of_shards": 1
},
"mappings": {
"properties": {
"title": {
"type": "text"
},
"city": {
"type": "keyword"
},
"price": {
"type": "double"
},
"create_time": {
"type": "date"
},
"full_room": {
"type": "boolean"
},
"location": {
"type": "geo_point"
},
"tags": {
"type": "keyword"
},
"comment_info": {
"properties": {
"favourable_comment": {
"type": "integer"
},
"negative_comment": {
"type": "integer"
}
}
}
}
}
}
# 导入数据
POST /_bulk
{"index": {"_index": "hotel","_id":"001"}}
{"title": "文雅酒假日酒店", "city": "北京", "price": 556.00, "create_time": "20200418120000", "full_room": true, "location": {"lat": 39.938838, "lon": 116.449112}, "tags": ["wifi", "小型电影院"], "comment_info": {"favourable_comment": 20, "negative_comment": 10}}
{"index": {"_index": "hotel","_id":"002"}}
{"title": "金都嘉怡假日酒店", "city": "北京", "create_time": "20210315200000", "full_room": false, "location": {"lat": 39.915153, "lon": 116.4030}, "tags": ["wifi", "免费早餐"], "comment_info": {"favourable_comment": 20, "negative_comment": 10}}
{"index": {"_index": "hotel","_id":"003"}}
{"title": "金都假日酒店", "city": "北京", "price": 200.00, "create_time": "20210509160000", "full_room": true, "location": {"lat": 40.002096, "lon": 116.376673}, "comment_info": {"favourable_comment": 20, "negative_comment": 10}}
{"index": {"_index": "hotel","_id":"004"}}
{"title": "金都假日酒店", "city": "天津", "price": 500.00, "create_time": "20210218080000", "full_room": false, "location": {"lat": 39.155004, "lon": 117.203976}, "tags": ["wifi", "免费车位"]}
{"index": {"_index": "hotel","_id":"005"}}
{"title": "文雅精选酒店", "city": "天津", "price": 800.00, "create_time": "20210101080000", "full_room": true, "location": {"lat": 39.178447, "lon": 117.219999}, "tags": ["wifi", "充电车位"], "comment_info": {"favourable_comment": 20, "negative_comment": 10}}
常见聚合指标 平均值
avg表示取平均值
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"avg": {
"field": "${field}" # 需要聚合的字段
}
}
}
}
# 示例
GET /hotel/_search
{
"size": 0,
"aggs": {
"my_aggs": {
"avg": {
"field": "price"
}
}
}
}
# 如果聚合的指标字段不是ES的基本类型,例如object类型,则可以使用点运算符进行引用
GET /hotel/_search
{
"size": 0,
"aggs": {
"my_aggs": {
"avg": {
"field": "comment_info.favourable_comment"
}
}
}
}
最大值
max表示取最大值
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"max": {
"field": "${field}" # 需要聚合的字段
}
}
}
}
最小值
min表示取最小值
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"min": {
"field": "${field}" # 需要聚合的字段
}
}
}
}
加和值
sum表示取加和值
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"sum": {
"field": "${field}", # 需要聚合的字段
"missing": ${num} # 可选字段,当值为空时,用${num}替代
}
}
}
}
值数量
value_count统计字段非空值的个数,数组中的每个非空元素都会计算进去
与_countAPI不同,其取的是索引中有多少个文档。
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"value_count": {
"field": "${field}" # 需要聚合的字段
}
}
}
}
统计
stats对常用统计指标进行了的聚合
# 语法
GET /${index_name}/_search
{
"size": 0, # 命中文档的数据不显示(没有分页作用)
"aggs": {
"${aggs_name}": { # 此聚合的名称
"stats": {
"field": "${field}" # 需要聚合的字段
}
}
}
}
# 输出信息中包含了非空值的数量、最大值、最小值、平均值、加和值。
"aggregations" : {
"stats" : {
"count" : 4,
"min" : 200.0,
"max" : 800.0,
"avg" : 514.0,
"sum" : 2056.0
}
}
桶聚合 单维度桶聚合
单维度桶聚合指的是按照一个维度对文档进行分组聚合。
terms聚合terms聚合是按照字段的关键字进行匹配和分组的,不能用于text类型的字段。
# 语法
GET /${index_name}/_search
{
"size": 0,
"aggs": {
"${aggs_name}": {
"terms": {
"field": "${field}",
"size": ${num} # 可选,输出聚合后的最大数量
}
}
}
}
# 示例
GET /hotel/_search
{
"size": 0,
"aggs": {
"my_aggs": {
"terms": {
"field": "city" # 聚合字段
}
}
}
} # 输出的是bucket,以及对应聚合字段下的文档数量
如果需要对单维度桶指定聚合指标,可以单独使用子aggs进行封装。
GET /hotel/_search
{
"size": 0,
"aggs": {
"my_aggs": {
"terms": {
"field": "city" # 先对城市进行聚合
},
"aggs": {
"my-sum": {
"sum": {
"field": "price" # 再将每个城市中所有酒店的价格聚合
}
}
}
}
}
}
ranges聚合
# 语法
GET /${index_name}/_search
{
"size": 0,
"aggs": {
"${aggs_name}": {
"range": {
"field": "${field}",
"ranges": [
{
# 指定from和to表示分组的起止数值
}
]
}
}
}
}
# 示例
GET /hotel/_search
{
"size": 0,
"aggs": {
"ra-aggs": {
"range": {
"field": "price",
"ranges": [
{
"to": 20 # 不指定from,则from默认为0
},
{
"from": 200,
"to": 500
},
{
"from": 500 # 不指定to,则to默认为该字段的最大值
}
]
}
}
}
}
多维度桶嵌套聚合
# 统计各个城市的满房和非满房状态下的酒店平均价格
GET /hotel/_search
{
"size": 0,
"aggs": {
"group_city": { # 多维度聚合桶名称
"terms": {
"field": "city"
},
"aggs": { # 单维度桶
"group_full_room": {
"terms": {
"field": "full_room"
},
"aggs": {
"my-sum": { # 聚合指标
"avg": {
"field": "price"
}
}
}
}
}
}
}
}
地理距离聚合
# 语法
GET /${index_name}/_search
{
"aggs": {
"${aggs_name}": {
"geo_distance": {
"field": "${field}",
"origin": {
"lat": ${num},
"lon": ${num}
},
"unit": "${unit}"
"ranges": [
{
"from": ${num},
"to": ${num}
}
]
}
}
}
}
# 示例
GET /hotel/_search
{
"size": 0,
"aggs": {
"1": {
"geo_distance": {
"field": "location",
"origin": {
"lat": 52.376,
"lon": 4.894
},
"unit": "km", # 单位,可选mi和km
"ranges": [ # 参考上面的ranges聚合,指定范围进行分组
{
"from": 10, # 表示10-50km以内的划分为一组
"to": 10000
}
]
},
"aggs": {
"2": {
"sum": { # 对上述聚合指定聚合指标
"field": "price"
}
}
}
}
}
}
聚合方式 直接聚合
直接聚合指的是聚合时的DSL没有query子句,是直接对索引内的所有文档进行聚合。前面介绍的示例都属于直接聚合。
先查询再聚合对查询出来的数据进行聚合
GET /hotel/_search
{
"size": 0,
"query": { # 查询语句
"term": {
"city": {
"value": "北京"
}
}
},
"aggs": { # 聚合语句
"my-agg": {
"avg": {
"field": "price"
}
}
}
}
前过滤器
对查询出的数据进一步过滤出符合条件的数据,然后再执行聚合。
GET /hotel/_search
{
"query": { # 查询语句
"term": {
"city": {
"value": "天津"
}
}
},
"aggs": {
"my-aggs": {
"filter": { # 过滤语句,过滤出符合条件的数据
"term": {
"full_room": false
}
},
"aggs": {
"my-avg": {
"avg": { # 对过滤过的数据进行聚合
"field": "price"
}
}
}
}
}
}
后过滤器
对查询出的数据进行聚合,再过滤出符合条件的数据。
GET /hotel/_search
{
"query": {
"match": {
"title": "假日"
}
},
"post_filter": {
"term": {
"city": "北京"
}
},
"aggs": {
"my-aggs": {
"avg": {
"field": "price"
}
}
}
}
聚合排序 按文档计数排序
GET /hotel/_search
{
"aggs": {
"group_city": {
"terms": {
"field": "city",
"order": {
"_count": "asc" # 按照输出中的doc_count字段由少到多排序
}
},
"aggs": {
"my-avg": {
"avg": {
"field": "price"
}
}
}
}
}
}
按聚合指标排序
GET /hotel/_search
{
"aggs": {
"group_city": {
"terms": {
"field": "city",
"order": {
"my-avg": "asc" # 按照聚合后的值,由少到多排序
}
},
"aggs": {
"my-avg": {
"avg": {
"field": "price"
}
}
}
}
}
}
按分组key排序
GET /hotel/_search
{
"aggs": {
"group_city": {
"terms": {
"field": "city",
"order": {
"_key": "asc" # 按照上述field字段(city)的值排序
}
},
"aggs": {
"my-avg": {
"avg": {
"field": "price"
}
}
}
}
}
}
聚合分页 Top hits聚合
Top hits聚合指的是聚合时在每个分组内部按照某个规则选出前N个文档进行展示。
当在索引中有大量数据命中时,Top hits聚合存在效率问题
# 语法
GET /${index_name}/_search
{
"aggs": {
"${aggs_name}": {
"top_hits": {
"size": 10
}
}
}
}
# 示例
GET /hotel/_search
{
"size": 0,
"query": {
"match": {
"title": "金都"
}
},
"aggs": {
"group_city": {
"terms": {
"field": "city" # 按照city分组
},
"aggs": {
"my-top": {
"top_hits": {
"size": 3 # 取出每个分组中按照分值降序的前3个文档
}
}
}
}
}
}
Collapse聚合
未达到书中描述的效果,实验每组只返回了1条数据,与from、size的值无关。
# 语法
GET /${index_name}/_search
{
"collapse": {
"field": "${field}"
}
}
# 示例
GET /hotel/_search
{
"from": 0,
"size": 5, # 此处指定的是分页显示聚合后的数据
"query": {
"match": {
"title": "金都"
}
},
"collapse": {
"field": "city" # 指定聚合的分组字段
}
}



