ES聚合Aggregation---原生(restful)api

原生的restful api:

聚合:只需要通过 aggs,然后通过不同的聚合属性,进行聚合。有多种聚合关系,可以嵌套(下钻) aggs;

ES中的聚合API的调用格式如下:

"aggregations" : {                  // 表示聚合操作,可以使用aggs替代
    "<aggregation_name>" : {        // 聚合名,可以是任意的字符串。用做响应的key,便于快速取得正确的响应数据。
        "<aggregation_type>" : {    // 聚合类别,就是各种类型的聚合,如min等
            <aggregation_body>      // 聚合体,不同的聚合有不同的body
        }
        [,"aggregations" : { [<sub_aggregation>]+ } ]? // 嵌套的子聚合,可以有0或多个
    }
    [,"<aggregation_name_2>" : { ... } ]* // 另外的聚合,可以有0或多个
}

demo:

第一个分析需求:计算每个tag下的商品数量

GET /ecommerce/product/_search
{
  "aggs": {
    "group_by_tags": {
      "terms": { "field": "tags" }
    }
  }
}
//group_by_tags是自己为聚合取的名字,可以随意改变,也是聚合结果返回字段的name



将文本field的fielddata属性设置为true

PUT /ecommerce/_mapping/product
{
  "properties": {
    "tags": {
      "type": "text",
      "fielddata": true
    }
  }
}

GET /ecommerce/product/_search
{
  "size": 0,
  "aggs": {
    "all_tags": {
      "terms": { "field": "tags" }
    }
  }
}

{
  "took": 20,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_tags": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "fangzhu",
          "doc_count": 2
        },
        {
          "key": "meibai",
          "doc_count": 2
        },
        {
          "key": "qingxin",
          "doc_count": 1
        }
      ]
    }
  }
}

----------------------------------------------------------------------------------------------------------------

第二个聚合分析的需求:对名称中包含yagao的商品,计算每个tag下的商品数量

GET /ecommerce/product/_search
{
  "size": 0,
  "query": {
    "match": {
      "name": "yagao"
    }
  },
  "aggs": {
    "all_tags": {
      "terms": {
        "field": "tags"
      }
    }
  }
}

----------------------------------------------------------------------------------------------------------------

第三个聚合分析的需求:先分组,再算每组的平均值,计算每个tag下的商品的平均价格

GET /ecommerce/product/_search
{
    "size": 0,
    "aggs" : {
        "group_by_tags" : {
            "terms" : { "field" : "tags" },
            "aggs" : {
                "avg_price" : {
                    "avg" : { "field" : "price" }
                }
            }
        }
    }
}

{
  "took": 8,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_tags": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "fangzhu",
          "doc_count": 2,
          "avg_price": {
            "value": 27.5
          }
        },
        {
          "key": "meibai",
          "doc_count": 2,
          "avg_price": {
            "value": 40
          }
        },
        {
          "key": "qingxin",
          "doc_count": 1,
          "avg_price": {
            "value": 40
          }
        }
      ]
    }
  }
}

----------------------------------------------------------------------------------------------------------------

第四个数据分析需求:计算每个tag下的商品的平均价格,并且按照平均价格降序排序

GET /ecommerce/product/_search
{
    "size": 0,
    "aggs" : {
        "all_tags" : {
            "terms" : { "field" : "tags", "order": { "avg_price": "desc" } },
            "aggs" : {
                "avg_price" : {
                    "avg" : { "field" : "price" }
                }
            }
        }
    }
}


----------------------------------------------------------------------------------------------------------------

第五个数据分析需求:按照指定的价格范围区间进行分组,然后在每组内再按照tag进行分组,最后再计算每组的平均价格

GET /ecommerce/product/_search
{
  "size": 0,
  "aggs": {
    "group_by_price": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "from": 0,
            "to": 20
          },
          {
            "from": 20,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_tags": {
          "terms": {
            "field": "tags"
          },
          "aggs": {
            "average_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        }
      }
    }
  }
}

重点来了:

1.度量类型(metric)聚合

Avg Aggregation:计算平均值。下面计算查询2班的年龄平均值,结果为21。


curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "query": {
    "term": {
      "classNo": "2"
    }
  },
  "aggs": {
    "avg_age": {
      "avg": {
        "field": "age"
      }
    }
  }
}
Stats Aggregation:统计查询,一次性统计出某个字段上的常用统计值。下面对整个学校的学生进行简单地统计。


curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "stats_age": {
      "stats": {
        "field": "age"
      }
    }
  }
}
'


返回:

{
  ...                     // 次要数据省略

  "aggregations": {
    "stats_age": {
      "count": 8,        // 含有年龄数据的学生计数
      "min": 16,         // 年龄最小值
      "max": 24,         // 年龄最大值
      "avg": 20.125,     // 年龄平均值
      "sum": 161,        // 年龄总和
      "min_as_string": "16.0",
      "max_as_string": "24.0",
      "avg_as_string": "20.125",
      "sum_as_string": "161.0"
    }
  }
}

Top hits Aggregation:
取符合条件的前n条数据记录。下面查询全校年龄排在前2位的学生,仅需返回学生姓名和年龄。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
{
  "aggs": {
    "top_age": {
      "top_hits": {
        "sort": [               // 排序
          {
            "age": {            // 按年龄降序
              "order": "desc"
            }
          }
        ],
        "_source": {
          "include": [           // 指定返回字段
            "name",
            "age"
          ]
        },
        "size": 2                 // 取前2条数据
      }
    }
  }
}



返回:

{
  ...

  "aggregations": {
    "top_age": {
      "hits": {
        "total": 9,
        "max_score": null,
        "hits": [
          {
            "_index": "student",
            "_type": "student",
            "_id": "1",
            "_score": null,
            "_source": {
              "name": "刘备",
              "age": "24"
            },
            "sort": [
              24
            ]
          },
          {
            "_index": "student",
            "_type": "student",
            "_id": "8",
            "_score": null,
            "_source": {
              "name": "赵云",
              "age": "23"
            },
            "sort": [
              23
            ]
          }
        ]
      }
    }
  }
}

2.桶类型(bucketing)聚合

(1)Terms Aggregation
按照指定的1或多个字段将数据划分成若干个小的区间,计算落在每一个区间上记录数量,并按指定顺序进行排序。下面统计每个班的学生数,并按学生数从大到小排序,取学生数靠前的2个班级。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "terms_classNo": {
      "terms": {
        "field": "classNo",            // 按照班号进行分组
        "order": {                     // 按学生数从大到小排序
          "_count": "desc"
        },
        "size": 2                      // 取前两名
      }
    }
  }
}
'

取得的前2名的学生数实际上是一个近似值。如果想要取得精确值,可以不指定size值,使其进行一次全排序,然后在程序中自行去取前2条记录。当然,这样做会使得ES做大量的排序运算工作,效率比较差。

(2)Range Aggregation
自定义区间范围的聚合,我们可以自己手动地划分区间,ES会根据划分出来的区间将数据分配不同的区间上去。下面将全校学生按照年龄划分为5个区间段:16岁以下、16~18、19~21、22~24、24岁以上,要求统计每一个年龄段内的学生数。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "range_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "to": 15
          },
          {
            "from": "16",
            "to": "18"
          },
          {
            "from": "19",
            "to": "21"
          },

          {
            "from": "22",
            "to": "24"
          },
          {
            "from": "25"
          }
        ]
      }
    }
  }
}
'
(3)Date Range Aggregation

时间区间聚合专门针对date类型的字段,它与Range Aggregation的主要区别是其可以使用时间运算表达式。主要包括+(加法)运算、-(减法)运算和/(四舍五入)运算,每种运算都可以作用在不同的时间域上面,下面是一些时间运算表达式示例。


now+10y:表示从现在开始的第10年。
now+10M:表示从现在开始的第10个月。
1990-01-10||+20y:表示从1990-01-01开始后的第20年,即2010-01-01。
now/y:表示在年位上做舍入运算。今天是2015-09-06,则这个表达式计算结果为:2015-01-01。说好的rounding运算呢?结果是做的flooring运算,不知道为啥,估计是我理解错了-_-!!


下面查询25年前及更早出生的学生数。
curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "range_age": {
      "date_range": {
        "field": "birthday",
        "ranges": [
          {
            "to": "now-25y"
          }
        ]
      }
    }
  }
}
'
(4)Histogram Aggregation

直方图聚合,它将某个number类型字段等分成n份,统计落在每一个区间内的记录数。它与前面介绍的Range聚合非常像,只不过Range可以任意划分区间,而Histogram做等间距划分。既然是等间距划分,那么参数里面必然有距离参数,就是interval参数。下面按学生年龄统计各个年龄段内的学生数量,分隔距离为2岁。


curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "histogram_age": {
      "histogram": {
        "field": "age",
        "interval": 2,               // 距离为2
        "min_doc_count": 1           // 只返回记录数量大于等于1的区间
      }
    }
  }
}
'
(5)Date Histogram Aggregation
时间直方图聚合,专门对时间类型的字段做直方图聚合。这种需求是比较常用见得的,我们在统计时,通常就会按照固定的时间断(1个月或1年等)来做统计。下面统计学校中同一年出生的学生数。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "data_histogram_birthday": {
      "date_histogram": {
        "field": "birthday",
        "interval": "year",              // 按年统计
        "format": "yyyy"                 // 返回结果的key的格式
      }
    }
  }
}
'


返回结果如下,可以看到由于上面的”format”: “yyyy”,所以返回的key_as_string只返回年的信息。

返回:
{
  "buckets": [
    {
      "key_as_string": "1985",
      "key": 473385600000,
      "doc_count": 1
    },
    {
      "key_as_string": "1986",
      "key": 504921600000,
      "doc_count": 1
    },
    {
      "key_as_string": "1987",
      "key": 536457600000,
      "doc_count": 1
    },
    {
      "key_as_string": "1989",
      "key": 599616000000,
      "doc_count": 1
    },
    {
      "key_as_string": "1990",
      "key": 631152000000,
      "doc_count": 1
    },
    {
      "key_as_string": "1991",
      "key": 662688000000,
      "doc_count": 1
    },
    {
      "key_as_string": "1992",
      "key": 694224000000,
      "doc_count": 1
    },
    {
      "key_as_string": "1994",
      "key": 757382400000,
      "doc_count": 1
    }
  ]
}
(6)Missing Aggregation
值缺损聚合,它是一类单桶聚合,也就是最终只会产生一个“桶”。下面统计学生信息中地址栏缺损的记录数量。由于只有学号为6的孙尚香的地址缺损,所以统计值为1。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d 
'
{
  "aggs": {
    "missing_address": {
      "missing": {
        "field": "address"
      }
    }
  }
}
'

1.3 嵌套使用

聚合操作是可以嵌套使用的。通过嵌套,可以使得metric类型的聚合操作作用在每一“桶”上。我们可以使用ES的嵌套聚合操作来完成稍微复杂一点的统计功能。下面统计每一个班里最大的年龄值。

curl -XPOST "192.168.1.101:9200/student/student/_search?search_type=count" -d
'
{
  "aggs": {
    "missing_address": {
      "terms": {
        "field": "classNo"
      },
      "aggs": {                 // 在这里嵌套新的子聚合
        "max_age": {
          "max": {              // 使用max聚合
            "field": "age"
          }
        }
      }
    }
  }
}
'

返回:

{
  "buckets": [
    {
      "key": "1",               // key是班级号
      "doc_count": 3,           // 每个班级内的人数
      "max_age": {              // 这里是我们指定的子聚合名
        "value": 24,            // 每班的年龄值
        "value_as_string": "24.0"
      }
    },
    {
      "key": "2",
      "doc_count": 3,
      "max_age": {
        "value": 23,
        "value_as_string": "23.0"
      }
    },
    {
      "key": "3",
      "doc_count": 1,
      "max_age": {
        "value": 20,
        "value_as_string": "20.0"
      }
    },
    {
      "key": "4",
      "doc_count": 1,
      "max_age": {
        "value": 16,
        "value_as_string": "16.0"
      }
    }
  ]
}

可参考:https://blog.csdn.net/xialei199023/article/details/48298635

原创文章 75 获赞 28 访问量 13万+

猜你喜欢

转载自blog.csdn.net/qq_33999844/article/details/86292666