# 8.1 메트릭 - Metrics Aggregations

### min, max, sum, avg

&#x20; 가장 흔하게 사용되는 metrics aggregations 은 **min**, **max**, **sum**, **avg** aggregation 입니다. 순서대로 명시한 필드의 **최소**, **최대**, **합**, **평균** 값을 가져오는 aggregation 입니다. 다음은 sum aggregation을 이용해서 my\_stations 에 있는 전체 데이터의 **passangers** 필드값의 합계를 가져오는 예제입니다.

{% tabs %}
{% tab title="request" %}
{% code title="my\_stations 인덱스의 passangers 필드 합 (sum) 을 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "all_passangers": {
      "sum": {
        "field": "passangers"
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="my\_stations 인덱스의 passangers 필드 합 (sum) 을 가져오는 aggs 결과" %}

```javascript
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "all_passangers" : {
      "value" : 41995.0
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; **min**, **max**, **avg** 들도 사용 방법은 동일하니 한번 해 보시기 바랍니다.

{% hint style="info" %}
aggregations 만 사용하는 경우에는 `"size": 0` 을 지정 하면 "hits": \[ ] 에 불필요한 도큐먼트 내용이 나타나지 않아 보기에도 편하고 도큐먼트를 fetch 해 오는 과정을 생략할 수 있어 쿼리 성능도 좋아집니다.
{% endhint %}

&#x20; aggregation해 오는 도큐먼트들은 같이 입력된 query 문의 영향을 받습니다. 다음은 my\_stations에서 `"station": "강남"` 인 도큐먼트들의 합계를 가져오는 예제입니다.

{% tabs %}
{% tab title="request" %}
{% code title="stations 값이 "강남" 인 도큐먼트들의 passangers 필드 합 (sum) 을 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "query": {
    "match": {
      "station": "강남"
    }
  },
  "size": 0,
  "aggs": {
    "gangnam_passangers": {
      "sum": {
        "field": "passangers"
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="stations 값이 "강남" 인 도큐먼트들의 passangers 필드 합 (sum) 을 가져오는 aggs 결과" %}

```javascript
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "gangnam_passangers" : {
      "value" : 29656.0
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 처음 쿼리와 다르게 전체 hits 결과는 5개이고 aggregation 결과도 **41995** 에서 **29656** 으로 줄어든 것을 확인할 수 있습니다.

### stats

&#x20; **min**, **max**, **sum**, **avg** 값을 모두 가져와야 한다면 다음과 같이 **stats** aggregation을 사용하면 위 4개의 값 모두와 count 값을 한번에 가져옵니다.

{% tabs %}
{% tab title="request" %}
{% code title="stats 로 passangers 필드의 min, max, sum, avg 값을 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0, 
  "aggs": {
    "passangers_stats": {
      "stats": {
        "field": "passangers"
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="stats 로 passangers 필드의 min, max, sum, avg 값을 가져오는 aggs 결과" %}

```javascript
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "passangers_stats" : {
      "count" : 10,
      "min" : 971.0,
      "max" : 6478.0,
      "avg" : 4199.5,
      "sum" : 41995.0
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### cardinality

&#x20; 필드의 값이 모두 몇 종류인지 분포값을 알려면 **cardinality** aggregation을 사용해서 구할 수 있습니다. Cardinality 는 일반적으로 text 필드에서는 사용할 수 없으며 **숫자** 필드나 **keyword**, **ip** 필드 등에 사용이 가능합니다. 사용자 접속 로그에서 IP 주소 필드를 가지고 실제로 접속한 사용자가 몇명인지 파악하는 등의 용도로 주로 사용됩니다. 다음은 my\_stations 인덱스에서 **line** 필드의 값이 몇 종류인지를 계산하는 예제입니다.

{% tabs %}
{% tab title="request" %}
{% code title="line 필드의 값이 몇 종류인지를 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "uniq_lines ": {
      "cardinality": {
        "field": "line.keyword"
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="line 필드의 값이 몇 종류인지를 가져오는 aggs 결과" %}

```javascript
{
  "took" : 15,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "uniq_lines " : {
      "value" : 3
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 위 쿼리 결과 `"uniq_lines " : { "value" : 3 }` 처럼 실제로 line 필드에는 "1호선", "2호선", "3호선" 총 3 종류의 값들이 있습니다.

### percentiles, percentile\_ranks

&#x20; 값들을 백분위 별로 보기 위해서 **percentiles** aggregation 의 사용이 가능합니다. 먼저 passangers 필드에 percentiles aggregation 적용 한 것을 확인 해 보겠습니다.

{% tabs %}
{% tab title="request" %}
{% code title="passangers 필드의 백분위를 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentiles": {
      "percentiles": {
        "field": "passangers"
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="passangers 필드의 백분위를 가져오는 aggs 결과" %}

```javascript
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "pass_percentiles" : {
      "values" : {
        "1.0" : 971.0000000000001,
        "5.0" : 971.0,
        "25.0" : 2314.0,
        "50.0" : 4766.5,
        "75.0" : 5821.0,
        "95.0" : 6478.0,
        "99.0" : 6478.0
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; percentiles aggregation은 디폴트로 **1%**, **5%**, **25%**, **50%**, **75%**, **95%**, **99%** 구간에 위치 해 있는 값들을 표시 해 줍니다. 백분위 구간을 직접 지정하고 싶으면 **percents** 옵션을 이용해서 지정이 가능합니다. 다음은 **20%**, **60%**, **80%** 백분위의 값을 가져오는 percentiles aggregation 입니다.

{% tabs %}
{% tab title="request" %}
{% code title="passangers 필드의 백분위를 지정해서 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentiles": {
      "percentiles": {
        "field": "passangers",
        "percents": [ 20, 60, 80 ]
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="passangers 필드의 백분위를 지정해서 가져오는 aggs 결과" %}

```javascript
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "pass_percentiles" : {
      "values" : {
        "20.0" : 1667.5,
        "60.0" : 5568.0,
        "80.0" : 6021.0
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; percentile\_ranks aggregation을 이용하면 반대로 값을 입력해서 그 값이 위치 해 있는 백분위를 볼 수 있습니다.

{% tabs %}
{% tab title="request" %}
{% code title="passangers 필드의 값을 지정해서 백분위를 가져오는 aggs" %}

```javascript
GET my_stations/_search
{
  "size": 0,
  "aggs": {
    "pass_percentile_ranks": {
      "percentile_ranks": {
        "field": "passangers",
        "values": [ 1000, 3000, 6000 ]
      }
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="passangers 필드의 값을 지정해서 백분위를 가져오는 aggs 결과" %}

```javascript
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 10,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  },
  "aggregations" : {
    "pass_percentile_ranks" : {
      "values" : {
        "1000.0" : 10.059568131049886,
        "3000.0" : 29.218263576617087,
        "6000.0" : 79.1549295774648
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20;  위 쿼리에서 입력한 passangers 값 **1000**, **3000**, **6000**이 각각 **10.059...%**, **29.218...%**, **79.154...%** 백분위에 위치 한 결과를 확인할 수 있습니다. **percentile\_ranks** aggregation 은 전체 수험생의 성적 중에서 특정 점수가 상위 몇% 에 있는지 등을 파악할 때 매우 편리하게 사용할 수 있습니다.
