From 18f4c1b3136437e0e470d2d9c4825a4763977265 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simonas=20=C5=A0erlinskas?= <simonas.serlinskas@nfq.com>
Date: Wed, 7 Sep 2016 10:30:15 +0300
Subject: [PATCH] moved all metric and bucketing aggs to its kind of namespace

---
 src/Aggregation/AvgAggregation.php            |  14 +-
 .../Bucketing/ChildrenAggregation.php         |  81 ++++++
 .../Bucketing/DateHistogramAggregation.php    |  87 +++++++
 .../Bucketing/DateRangeAggregation.php        | 123 +++++++++
 .../Bucketing/FilterAggregation.php           |  84 +++++++
 .../Bucketing/FiltersAggregation.php          | 106 ++++++++
 .../Bucketing/GeoDistanceAggregation.php      | 186 ++++++++++++++
 .../Bucketing/GeoHashGridAggregation.php      | 143 +++++++++++
 .../Bucketing/GlobalAggregation.php           |  49 ++++
 .../Bucketing/HistogramAggregation.php        | 237 ++++++++++++++++++
 .../Bucketing/Ipv4RangeAggregation.php        | 111 ++++++++
 .../Bucketing/MissingAggregation.php          |  57 +++++
 .../Bucketing/NestedAggregation.php           |  79 ++++++
 .../Bucketing/RangeAggregation.php            | 166 ++++++++++++
 .../Bucketing/ReverseNestedAggregation.php    |  88 +++++++
 .../Bucketing/SamplerAggregation.php          |  85 +++++++
 .../Bucketing/SignificantTermsAggregation.php |  28 +++
 .../Bucketing/TermsAggregation.php            |  65 +++++
 src/Aggregation/CardinalityAggregation.php    |  98 +-------
 src/Aggregation/ChildrenAggregation.php       |  64 +----
 src/Aggregation/DateHistogramAggregation.php  |  73 +-----
 src/Aggregation/DateRangeAggregation.php      | 106 +-------
 src/Aggregation/ExtendedStatsAggregation.php  |  75 +-----
 src/Aggregation/FilterAggregation.php         |  66 +----
 src/Aggregation/FiltersAggregation.php        |  89 +------
 src/Aggregation/GeoBoundsAggregation.php      |  69 +----
 src/Aggregation/GeoCentroidAggregation.php    |  44 +---
 src/Aggregation/GeoDistanceAggregation.php    | 169 +------------
 src/Aggregation/GeoHashGridAggregation.php    | 125 +--------
 src/Aggregation/GlobalAggregation.php         |  32 +--
 src/Aggregation/HistogramAggregation.php      | 220 +---------------
 src/Aggregation/Ipv4RangeAggregation.php      |  94 +------
 src/Aggregation/MaxAggregation.php            |  14 +-
 src/Aggregation/Metric/AvgAggregation.php     |  28 +++
 .../Metric/CardinalityAggregation.php         | 115 +++++++++
 .../Metric/ExtendedStatsAggregation.php       |  92 +++++++
 .../Metric/GeoBoundsAggregation.php           |  86 +++++++
 .../Metric/GeoCentroidAggregation.php         |  61 +++++
 src/Aggregation/Metric/MaxAggregation.php     |  28 +++
 src/Aggregation/Metric/MinAggregation.php     |  28 +++
 .../Metric/PercentileRanksAggregation.php     | 134 ++++++++++
 .../Metric/PercentilesAggregation.php         | 130 ++++++++++
 .../Metric/ScriptedMetricAggregation.php      | 158 ++++++++++++
 src/Aggregation/Metric/StatsAggregation.php   |  66 +++++
 src/Aggregation/Metric/SumAggregation.php     |  28 +++
 src/Aggregation/Metric/TopHitsAggregation.php | 146 +++++++++++
 .../Metric/ValueCountAggregation.php          |  28 +++
 src/Aggregation/MinAggregation.php            |  14 +-
 src/Aggregation/MissingAggregation.php        |  40 +--
 src/Aggregation/NestedAggregation.php         |  62 +----
 .../PercentileRanksAggregation.php            | 117 +--------
 src/Aggregation/PercentilesAggregation.php    | 113 +--------
 src/Aggregation/RangeAggregation.php          | 149 +----------
 src/Aggregation/ReverseNestedAggregation.php  |  71 +-----
 src/Aggregation/SamplerAggregation.php        |  71 +-----
 .../SignificantTermsAggregation.php           |  14 +-
 src/Aggregation/StatsAggregation.php          |  49 +---
 src/Aggregation/SumAggregation.php            |  14 +-
 src/Aggregation/TermsAggregation.php          |  48 +---
 src/Aggregation/TopHitsAggregation.php        | 127 +---------
 src/Aggregation/ValueCountAggregation.php     |  14 +-
 src/SearchEndpoint/InnerHitsEndpoint.php      |   4 +-
 62 files changed, 3061 insertions(+), 2101 deletions(-)
 create mode 100644 src/Aggregation/Bucketing/ChildrenAggregation.php
 create mode 100644 src/Aggregation/Bucketing/DateHistogramAggregation.php
 create mode 100644 src/Aggregation/Bucketing/DateRangeAggregation.php
 create mode 100644 src/Aggregation/Bucketing/FilterAggregation.php
 create mode 100644 src/Aggregation/Bucketing/FiltersAggregation.php
 create mode 100644 src/Aggregation/Bucketing/GeoDistanceAggregation.php
 create mode 100644 src/Aggregation/Bucketing/GeoHashGridAggregation.php
 create mode 100644 src/Aggregation/Bucketing/GlobalAggregation.php
 create mode 100644 src/Aggregation/Bucketing/HistogramAggregation.php
 create mode 100644 src/Aggregation/Bucketing/Ipv4RangeAggregation.php
 create mode 100644 src/Aggregation/Bucketing/MissingAggregation.php
 create mode 100644 src/Aggregation/Bucketing/NestedAggregation.php
 create mode 100644 src/Aggregation/Bucketing/RangeAggregation.php
 create mode 100644 src/Aggregation/Bucketing/ReverseNestedAggregation.php
 create mode 100644 src/Aggregation/Bucketing/SamplerAggregation.php
 create mode 100644 src/Aggregation/Bucketing/SignificantTermsAggregation.php
 create mode 100644 src/Aggregation/Bucketing/TermsAggregation.php
 create mode 100644 src/Aggregation/Metric/AvgAggregation.php
 create mode 100644 src/Aggregation/Metric/CardinalityAggregation.php
 create mode 100644 src/Aggregation/Metric/ExtendedStatsAggregation.php
 create mode 100644 src/Aggregation/Metric/GeoBoundsAggregation.php
 create mode 100644 src/Aggregation/Metric/GeoCentroidAggregation.php
 create mode 100644 src/Aggregation/Metric/MaxAggregation.php
 create mode 100644 src/Aggregation/Metric/MinAggregation.php
 create mode 100644 src/Aggregation/Metric/PercentileRanksAggregation.php
 create mode 100644 src/Aggregation/Metric/PercentilesAggregation.php
 create mode 100644 src/Aggregation/Metric/ScriptedMetricAggregation.php
 create mode 100644 src/Aggregation/Metric/StatsAggregation.php
 create mode 100644 src/Aggregation/Metric/SumAggregation.php
 create mode 100644 src/Aggregation/Metric/TopHitsAggregation.php
 create mode 100644 src/Aggregation/Metric/ValueCountAggregation.php

diff --git a/src/Aggregation/AvgAggregation.php b/src/Aggregation/AvgAggregation.php
index 11b8886..0275168 100644
--- a/src/Aggregation/AvgAggregation.php
+++ b/src/Aggregation/AvgAggregation.php
@@ -11,16 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Metric\AvgAggregation as Base;
+
 /**
  * Class representing Avg Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class AvgAggregation extends StatsAggregation
+class AvgAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'avg';
-    }
 }
diff --git a/src/Aggregation/Bucketing/ChildrenAggregation.php b/src/Aggregation/Bucketing/ChildrenAggregation.php
new file mode 100644
index 0000000..f85e2e8
--- /dev/null
+++ b/src/Aggregation/Bucketing/ChildrenAggregation.php
@@ -0,0 +1,81 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing ChildrenAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-children-aggregation.html
+ */
+class ChildrenAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var string
+     */
+    private $children;
+
+    /**
+     * Return children.
+     *
+     * @return string
+     */
+    public function getChildren()
+    {
+        return $this->children;
+    }
+
+    /**
+     * @param string $name
+     * @param string $children
+     */
+    public function __construct($name, $children = null)
+    {
+        parent::__construct($name);
+
+        $this->setChildren($children);
+    }
+
+    /**
+     * Sets children.
+     *
+     * @param string $children
+     */
+    public function setChildren($children)
+    {
+        $this->children = $children;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'children';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if (count($this->getAggregations()) == 0) {
+            throw new \LogicException("Children aggregation `{$this->getName()}` has no aggregations added");
+        }
+
+        return ['type' => $this->getChildren()];
+    }
+}
diff --git a/src/Aggregation/Bucketing/DateHistogramAggregation.php b/src/Aggregation/Bucketing/DateHistogramAggregation.php
new file mode 100644
index 0000000..41e5386
--- /dev/null
+++ b/src/Aggregation/Bucketing/DateHistogramAggregation.php
@@ -0,0 +1,87 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing Histogram aggregation.
+ *
+ * @link https://goo.gl/hGCdDd
+ */
+class DateHistogramAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var string
+     */
+    protected $interval;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param string $interval
+     */
+    public function __construct($name, $field = null, $interval = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setInterval($interval);
+    }
+
+    /**
+     * @return int
+     */
+    public function getInterval()
+    {
+        return $this->interval;
+    }
+
+    /**
+     * @param string $interval
+     */
+    public function setInterval($interval)
+    {
+        $this->interval = $interval;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'date_histogram';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if (!$this->getField() || !$this->getInterval()) {
+            throw new \LogicException('Date histogram aggregation must have field and interval set.');
+        }
+
+        $out = [
+            'field' => $this->getField(),
+            'interval' => $this->getInterval(),
+        ];
+        $out = $this->processArray($out);
+
+        return $out;
+    }
+}
diff --git a/src/Aggregation/Bucketing/DateRangeAggregation.php b/src/Aggregation/Bucketing/DateRangeAggregation.php
new file mode 100644
index 0000000..4de68cc
--- /dev/null
+++ b/src/Aggregation/Bucketing/DateRangeAggregation.php
@@ -0,0 +1,123 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing date range aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-daterange-aggregation.html
+ */
+class DateRangeAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var string
+     */
+    private $format;
+
+    /**
+     * @return string
+     */
+    public function getFormat()
+    {
+        return $this->format;
+    }
+
+    /**
+     * @param string $name
+     * @param string $field
+     * @param string $format
+     * @param array  $ranges
+     */
+    public function __construct($name, $field = null, $format = null, array $ranges = [])
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setFormat($format);
+        foreach ($ranges as $range) {
+            $from = isset($range['from']) ? $range['from'] : null;
+            $to = isset($range['to']) ? $range['to'] : null;
+            $this->addRange($from, $to);
+        }
+    }
+
+    /**
+     * @param string $format
+     */
+    public function setFormat($format)
+    {
+        $this->format = $format;
+    }
+
+    /**
+     * @var array
+     */
+    private $ranges = [];
+
+    /**
+     * Add range to aggregation.
+     *
+     * @param string|null $from
+     * @param string|null $to
+     *
+     * @return RangeAggregation
+     *
+     * @throws \LogicException
+     */
+    public function addRange($from = null, $to = null)
+    {
+        $range = array_filter(
+            [
+                'from' => $from,
+                'to' => $to,
+            ]
+        );
+
+        if (empty($range)) {
+            throw new \LogicException('Either from or to must be set. Both cannot be null.');
+        }
+
+        $this->ranges[] = $range;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if ($this->getField() && $this->getFormat() && !empty($this->ranges)) {
+            $data = [
+                'format' => $this->getFormat(),
+                'field' => $this->getField(),
+                'ranges' => $this->ranges,
+            ];
+
+            return $data;
+        }
+        throw new \LogicException('Date range aggregation must have field, format set and range added.');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'date_range';
+    }
+}
diff --git a/src/Aggregation/Bucketing/FilterAggregation.php b/src/Aggregation/Bucketing/FilterAggregation.php
new file mode 100644
index 0000000..b30a8ed
--- /dev/null
+++ b/src/Aggregation/Bucketing/FilterAggregation.php
@@ -0,0 +1,84 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\BuilderInterface;
+
+/**
+ * Class representing FilterAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filter-aggregation.html
+ */
+class FilterAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var BuilderInterface
+     */
+    protected $filter;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string           $name
+     * @param BuilderInterface $filter
+     */
+    public function __construct($name, BuilderInterface $filter = null)
+    {
+        parent::__construct($name);
+
+        if ($filter !== null) {
+            $this->setFilter($filter);
+        }
+    }
+
+    /**
+     * Sets a filter.
+     *
+     * @param BuilderInterface $filter
+     */
+    public function setFilter(BuilderInterface $filter)
+    {
+        $this->filter = $filter;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setField($field)
+    {
+        throw new \LogicException("Filter aggregation, doesn't support `field` parameter");
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if (!$this->filter) {
+            throw new \LogicException("Filter aggregation `{$this->getName()}` has no filter added");
+        }
+
+        return $this->filter->toArray();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'filter';
+    }
+}
diff --git a/src/Aggregation/Bucketing/FiltersAggregation.php b/src/Aggregation/Bucketing/FiltersAggregation.php
new file mode 100644
index 0000000..bcff22f
--- /dev/null
+++ b/src/Aggregation/Bucketing/FiltersAggregation.php
@@ -0,0 +1,106 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\BuilderInterface;
+
+/**
+ * Class representing filters aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-filters-aggregation.html
+ */
+class FiltersAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var BuilderInterface[]
+     */
+    private $filters = [];
+
+    /**
+     * @var bool
+     */
+    private $anonymous = false;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string             $name
+     * @param BuilderInterface[] $filters
+     * @param bool               $anonymous
+     */
+    public function __construct($name, $filters = [], $anonymous = false)
+    {
+        parent::__construct($name);
+
+        $this->setAnonymous($anonymous);
+        foreach ($filters as $name => $filter) {
+            if ($anonymous) {
+                $this->addFilter($filter);
+            } else {
+                $this->addFilter($filter, $name);
+            }
+        }
+    }
+
+    /**
+     * @param bool $anonymous
+     *
+     * @return FiltersAggregation
+     */
+    public function setAnonymous($anonymous)
+    {
+        $this->anonymous = $anonymous;
+
+        return $this;
+    }
+
+    /**
+     * @param BuilderInterface $filter
+     * @param string           $name
+     *
+     * @throws \LogicException
+     *
+     * @return FiltersAggregation
+     */
+    public function addFilter(BuilderInterface $filter, $name = '')
+    {
+        if ($this->anonymous === false && empty($name)) {
+            throw new \LogicException('In not anonymous filters filter name must be set.');
+        } elseif ($this->anonymous === false && !empty($name)) {
+            $this->filters['filters'][$name] = $filter->toArray();
+        } else {
+            $this->filters['filters'][] = $filter->toArray();
+        }
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        return $this->filters;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'filters';
+    }
+}
diff --git a/src/Aggregation/Bucketing/GeoDistanceAggregation.php b/src/Aggregation/Bucketing/GeoDistanceAggregation.php
new file mode 100644
index 0000000..2d6a095
--- /dev/null
+++ b/src/Aggregation/Bucketing/GeoDistanceAggregation.php
@@ -0,0 +1,186 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing geo distance aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geodistance-aggregation.html
+ */
+class GeoDistanceAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var mixed
+     */
+    private $origin;
+
+    /**
+     * @var string
+     */
+    private $distanceType;
+
+    /**
+     * @var string
+     */
+    private $unit;
+
+    /**
+     * @var array
+     */
+    private $ranges = [];
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param mixed  $origin
+     * @param array  $ranges
+     * @param string $unit
+     * @param string $distanceType
+     */
+    public function __construct($name, $field = null, $origin = null, $ranges = [], $unit = null, $distanceType = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setOrigin($origin);
+        foreach ($ranges as $range) {
+            $from = isset($range['from']) ? $range['from'] : null;
+            $to = isset($range['to']) ? $range['to'] : null;
+            $this->addRange($from, $to);
+        }
+        $this->setUnit($unit);
+        $this->setDistanceType($distanceType);
+    }
+
+    /**
+     * @return string
+     */
+    public function getOrigin()
+    {
+        return $this->origin;
+    }
+
+    /**
+     * @param mixed $origin
+     */
+    public function setOrigin($origin)
+    {
+        $this->origin = $origin;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDistanceType()
+    {
+        return $this->distanceType;
+    }
+
+    /**
+     * @param string $distanceType
+     */
+    public function setDistanceType($distanceType)
+    {
+        $this->distanceType = $distanceType;
+    }
+
+    /**
+     * @return string
+     */
+    public function getUnit()
+    {
+        return $this->unit;
+    }
+
+    /**
+     * @param string $unit
+     */
+    public function setUnit($unit)
+    {
+        $this->unit = $unit;
+    }
+
+    /**
+     * Add range to aggregation.
+     *
+     * @param int|float|null $from
+     * @param int|float|null $to
+     *
+     * @throws \LogicException
+     *
+     * @return GeoDistanceAggregation
+     */
+    public function addRange($from = null, $to = null)
+    {
+        $range = array_filter(
+            [
+                'from' => $from,
+                'to' => $to,
+            ]
+        );
+
+        if (empty($range)) {
+            throw new \LogicException('Either from or to must be set. Both cannot be null.');
+        }
+
+        $this->ranges[] = $range;
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = [];
+
+        if ($this->getField()) {
+            $data['field'] = $this->getField();
+        } else {
+            throw new \LogicException('Geo distance aggregation must have a field set.');
+        }
+
+        if ($this->getOrigin()) {
+            $data['origin'] = $this->getOrigin();
+        } else {
+            throw new \LogicException('Geo distance aggregation must have an origin set.');
+        }
+
+        if ($this->getUnit()) {
+            $data['unit'] = $this->getUnit();
+        }
+
+        if ($this->getDistanceType()) {
+            $data['distance_type'] = $this->getDistanceType();
+        }
+
+        $data['ranges'] = $this->ranges;
+
+        return $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'geo_distance';
+    }
+}
diff --git a/src/Aggregation/Bucketing/GeoHashGridAggregation.php b/src/Aggregation/Bucketing/GeoHashGridAggregation.php
new file mode 100644
index 0000000..cf7fff9
--- /dev/null
+++ b/src/Aggregation/Bucketing/GeoHashGridAggregation.php
@@ -0,0 +1,143 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing geohash grid aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-geohashgrid-aggregation.html
+ */
+class GeoHashGridAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var int
+     */
+    private $precision;
+
+    /**
+     * @var int
+     */
+    private $size;
+
+    /**
+     * @var int
+     */
+    private $shardSize;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param int    $precision
+     * @param int    $size
+     * @param int    $shardSize
+     */
+    public function __construct($name, $field = null, $precision = null, $size = null, $shardSize = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setPrecision($precision);
+        $this->setSize($size);
+        $this->setShardSize($shardSize);
+    }
+
+    /**
+     * @return int
+     */
+    public function getPrecision()
+    {
+        return $this->precision;
+    }
+
+    /**
+     * @param int $precision
+     */
+    public function setPrecision($precision)
+    {
+        $this->precision = $precision;
+    }
+
+    /**
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * @param int $size
+     */
+    public function setSize($size)
+    {
+        $this->size = $size;
+    }
+
+    /**
+     * @return int
+     */
+    public function getShardSize()
+    {
+        return $this->shardSize;
+    }
+
+    /**
+     * @param int $shardSize
+     */
+    public function setShardSize($shardSize)
+    {
+        $this->shardSize = $shardSize;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = [];
+
+        if ($this->getField()) {
+            $data['field'] = $this->getField();
+        } else {
+            throw new \LogicException('Geo bounds aggregation must have a field set.');
+        }
+
+        if ($this->getPrecision()) {
+            $data['precision'] = $this->getPrecision();
+        }
+
+        if ($this->getSize()) {
+            $data['size'] = $this->getSize();
+        }
+
+        if ($this->getShardSize()) {
+            $data['shard_size'] = $this->getShardSize();
+        }
+
+        return $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'geohash_grid';
+    }
+}
diff --git a/src/Aggregation/Bucketing/GlobalAggregation.php b/src/Aggregation/Bucketing/GlobalAggregation.php
new file mode 100644
index 0000000..badd85c
--- /dev/null
+++ b/src/Aggregation/Bucketing/GlobalAggregation.php
@@ -0,0 +1,49 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing GlobalAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-global-aggregation.html
+ */
+class GlobalAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function setField($field)
+    {
+        throw new \LogicException("Global aggregation, doesn't support `field` parameter");
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'global';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        return new \stdClass();
+    }
+}
diff --git a/src/Aggregation/Bucketing/HistogramAggregation.php b/src/Aggregation/Bucketing/HistogramAggregation.php
new file mode 100644
index 0000000..5fc98c2
--- /dev/null
+++ b/src/Aggregation/Bucketing/HistogramAggregation.php
@@ -0,0 +1,237 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing Histogram aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-histogram-aggregation.html
+ */
+class HistogramAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    const DIRECTION_ASC = 'asc';
+    const DIRECTION_DESC = 'desc';
+
+    /**
+     * @var int
+     */
+    protected $interval;
+
+    /**
+     * @var int
+     */
+    protected $minDocCount;
+
+    /**
+     * @var array
+     */
+    protected $extendedBounds;
+
+    /**
+     * @var string
+     */
+    protected $orderMode;
+
+    /**
+     * @var string
+     */
+    protected $orderDirection;
+
+    /**
+     * @var bool
+     */
+    protected $keyed;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param int    $interval
+     * @param int    $minDocCount
+     * @param string $orderMode
+     * @param string $orderDirection
+     * @param int    $extendedBoundsMin
+     * @param int    $extendedBoundsMax
+     * @param bool   $keyed
+     */
+    public function __construct(
+        $name,
+        $field = null,
+        $interval = null,
+        $minDocCount = null,
+        $orderMode = null,
+        $orderDirection = self::DIRECTION_ASC,
+        $extendedBoundsMin = null,
+        $extendedBoundsMax = null,
+        $keyed = null
+    ) {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setInterval($interval);
+        $this->setMinDocCount($minDocCount);
+        $this->setOrder($orderMode, $orderDirection);
+        $this->setExtendedBounds($extendedBoundsMin, $extendedBoundsMax);
+        $this->setKeyed($keyed);
+    }
+
+    /**
+     * @return bool
+     */
+    public function isKeyed()
+    {
+        return $this->keyed;
+    }
+
+    /**
+     * Get response as a hash instead keyed by the buckets keys.
+     *
+     * @param bool $keyed
+     */
+    public function setKeyed($keyed)
+    {
+        $this->keyed = $keyed;
+    }
+
+    /**
+     * Sets buckets ordering.
+     *
+     * @param string $mode
+     * @param string $direction
+     */
+    public function setOrder($mode, $direction = self::DIRECTION_ASC)
+    {
+        $this->orderMode = $mode;
+        $this->orderDirection = $direction;
+    }
+
+    /**
+     * @return array
+     */
+    public function getOrder()
+    {
+        if ($this->orderMode && $this->orderDirection) {
+            return [$this->orderMode => $this->orderDirection];
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @return int
+     */
+    public function getInterval()
+    {
+        return $this->interval;
+    }
+
+    /**
+     * @param int $interval
+     */
+    public function setInterval($interval)
+    {
+        $this->interval = $interval;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMinDocCount()
+    {
+        return $this->minDocCount;
+    }
+
+    /**
+     * Set limit for document count buckets should have.
+     *
+     * @param int $minDocCount
+     */
+    public function setMinDocCount($minDocCount)
+    {
+        $this->minDocCount = $minDocCount;
+    }
+
+    /**
+     * @return array
+     */
+    public function getExtendedBounds()
+    {
+        return $this->extendedBounds;
+    }
+
+    /**
+     * @param int $min
+     * @param int $max
+     */
+    public function setExtendedBounds($min = null, $max = null)
+    {
+        $bounds = array_filter(
+            [
+                'min' => $min,
+                'max' => $max,
+            ]
+        );
+        $this->extendedBounds = $bounds;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'histogram';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'field' => $this->getField(),
+                'interval' => $this->getInterval(),
+                'min_doc_count' => $this->getMinDocCount(),
+                'extended_bounds' => $this->getExtendedBounds(),
+                'keyed' => $this->isKeyed(),
+                'order' => $this->getOrder(),
+            ],
+            function ($val) {
+                return ($val || is_numeric($val));
+            }
+        );
+        $this->checkRequiredParameters($out, ['field', 'interval']);
+
+        return $out;
+    }
+
+    /**
+     * Checks if all required parameters are set.
+     *
+     * @param array $data
+     * @param array $required
+     *
+     * @throws \LogicException
+     */
+    protected function checkRequiredParameters($data, $required)
+    {
+        if (count(array_intersect_key(array_flip($required), $data)) !== count($required)) {
+            throw new \LogicException('Histogram aggregation must have field and interval set.');
+        }
+    }
+}
diff --git a/src/Aggregation/Bucketing/Ipv4RangeAggregation.php b/src/Aggregation/Bucketing/Ipv4RangeAggregation.php
new file mode 100644
index 0000000..d9bcd0b
--- /dev/null
+++ b/src/Aggregation/Bucketing/Ipv4RangeAggregation.php
@@ -0,0 +1,111 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing ip range aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-iprange-aggregation.html
+ */
+class Ipv4RangeAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var array
+     */
+    private $ranges = [];
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param array  $ranges
+     */
+    public function __construct($name, $field = null, $ranges = [])
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        foreach ($ranges as $range) {
+            if (is_array($range)) {
+                $from = isset($range['from']) ? $range['from'] : null;
+                $to = isset($range['to']) ? $range['to'] : null;
+                $this->addRange($from, $to);
+            } else {
+                $this->addMask($range);
+            }
+        }
+    }
+
+    /**
+     * Add range to aggregation.
+     *
+     * @param string|null $from
+     * @param string|null $to
+     *
+     * @return Ipv4RangeAggregation
+     */
+    public function addRange($from = null, $to = null)
+    {
+        $range = array_filter(
+            [
+                'from' => $from,
+                'to' => $to,
+            ]
+        );
+
+        $this->ranges[] = $range;
+
+        return $this;
+    }
+
+    /**
+     * Add ip mask to aggregation.
+     *
+     * @param string $mask
+     *
+     * @return Ipv4RangeAggregation
+     */
+    public function addMask($mask)
+    {
+        $this->ranges[] = ['mask' => $mask];
+
+        return $this;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'ip_range';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if ($this->getField() && !empty($this->ranges)) {
+            return [
+                'field' => $this->getField(),
+                'ranges' => array_values($this->ranges),
+            ];
+        }
+        throw new \LogicException('Ip range aggregation must have field set and range added.');
+    }
+}
diff --git a/src/Aggregation/Bucketing/MissingAggregation.php b/src/Aggregation/Bucketing/MissingAggregation.php
new file mode 100644
index 0000000..2cffa14
--- /dev/null
+++ b/src/Aggregation/Bucketing/MissingAggregation.php
@@ -0,0 +1,57 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing missing aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-missing-aggregation.html
+ */
+class MissingAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     */
+    public function __construct($name, $field = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if ($this->getField()) {
+            return ['field' => $this->getField()];
+        }
+        throw new \LogicException('Missing aggregation must have a field set.');
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'missing';
+    }
+}
diff --git a/src/Aggregation/Bucketing/NestedAggregation.php b/src/Aggregation/Bucketing/NestedAggregation.php
new file mode 100644
index 0000000..237318b
--- /dev/null
+++ b/src/Aggregation/Bucketing/NestedAggregation.php
@@ -0,0 +1,79 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing NestedAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-nested-aggregation.html
+ */
+class NestedAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $path
+     */
+    public function __construct($name, $path = null)
+    {
+        parent::__construct($name);
+
+        $this->setPath($path);
+    }
+
+    /**
+     * Return path.
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Sets path.
+     *
+     * @param string $path
+     */
+    public function setPath($path)
+    {
+        $this->path = $path;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'nested';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        return ['path' => $this->getPath()];
+    }
+}
diff --git a/src/Aggregation/Bucketing/RangeAggregation.php b/src/Aggregation/Bucketing/RangeAggregation.php
new file mode 100644
index 0000000..ab87c99
--- /dev/null
+++ b/src/Aggregation/Bucketing/RangeAggregation.php
@@ -0,0 +1,166 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing RangeAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-range-aggregation.html
+ */
+class RangeAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var array
+     */
+    private $ranges = [];
+
+    /**
+     * @var bool
+     */
+    private $keyed = false;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param array  $ranges
+     * @param bool   $keyed
+     */
+    public function __construct($name, $field = null, $ranges = [], $keyed = false)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setKeyed($keyed);
+        foreach ($ranges as $range) {
+            $from = isset($range['from']) ? $range['from'] : null;
+            $to = isset($range['to']) ? $range['to'] : null;
+            $key = isset($range['key']) ? $range['key'] : null;
+            $this->addRange($from, $to, $key);
+        }
+    }
+
+    /**
+     * Sets if result buckets should be keyed.
+     *
+     * @param bool $keyed
+     *
+     * @return RangeAggregation
+     */
+    public function setKeyed($keyed)
+    {
+        $this->keyed = $keyed;
+
+        return $this;
+    }
+
+    /**
+     * Add range to aggregation.
+     *
+     * @param int|float|null $from
+     * @param int|float|null $to
+     * @param string         $key
+     *
+     * @return RangeAggregation
+     */
+    public function addRange($from = null, $to = null, $key = '')
+    {
+        $range = array_filter(
+            [
+                'from' => $from,
+                'to' => $to,
+            ]
+        );
+
+        if ($this->keyed && !empty($key)) {
+            $range['key'] = $key;
+        }
+
+        $this->ranges[] = $range;
+
+        return $this;
+    }
+
+    /**
+     * Remove range from aggregation. Returns true on success.
+     *
+     * @param int|float|null $from
+     * @param int|float|null $to
+     *
+     * @return bool
+     */
+    public function removeRange($from, $to)
+    {
+        foreach ($this->ranges as $key => $range) {
+            if (array_diff_assoc(array_filter(['from' => $from, 'to' => $to]), $range) === []) {
+                unset($this->ranges[$key]);
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Removes range by key.
+     *
+     * @param string $key Range key.
+     *
+     * @return bool
+     */
+    public function removeRangeByKey($key)
+    {
+        if ($this->keyed) {
+            foreach ($this->ranges as $rangeKey => $range) {
+                if (array_key_exists('key', $range) && $range['key'] === $key) {
+                    unset($this->ranges[$rangeKey]);
+
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = [
+            'keyed' => $this->keyed,
+            'ranges' => array_values($this->ranges),
+        ];
+
+        if ($this->getField()) {
+            $data['field'] = $this->getField();
+        }
+
+        return $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'range';
+    }
+}
diff --git a/src/Aggregation/Bucketing/ReverseNestedAggregation.php b/src/Aggregation/Bucketing/ReverseNestedAggregation.php
new file mode 100644
index 0000000..66dd066
--- /dev/null
+++ b/src/Aggregation/Bucketing/ReverseNestedAggregation.php
@@ -0,0 +1,88 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing ReverseNestedAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-reverse-nested-aggregation.html
+ */
+class ReverseNestedAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * @var string
+     */
+    private $path;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $path
+     */
+    public function __construct($name, $path = null)
+    {
+        parent::__construct($name);
+
+        $this->setPath($path);
+    }
+
+    /**
+     * Return path.
+     *
+     * @return string
+     */
+    public function getPath()
+    {
+        return $this->path;
+    }
+
+    /**
+     * Sets path.
+     *
+     * @param string $path
+     */
+    public function setPath($path)
+    {
+        $this->path = $path;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'reverse_nested';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        if (count($this->getAggregations()) == 0) {
+            throw new \LogicException("Reverse Nested aggregation `{$this->getName()}` has no aggregations added");
+        }
+
+        $output = new \stdClass();
+        if ($this->getPath()) {
+            $output = ['path' => $this->getPath()];
+        }
+
+        return $output;
+    }
+}
diff --git a/src/Aggregation/Bucketing/SamplerAggregation.php b/src/Aggregation/Bucketing/SamplerAggregation.php
new file mode 100644
index 0000000..1a09079
--- /dev/null
+++ b/src/Aggregation/Bucketing/SamplerAggregation.php
@@ -0,0 +1,85 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+
+/**
+ * Class representing geo bounds aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/2.3/search-aggregations-bucket-sampler-aggregation.html
+ */
+class SamplerAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+
+    /**
+     * Defines how many results will be received from each shard
+     * @param string $shardSize
+     */
+    private $shardSize;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param int    $shardSize
+     */
+    public function __construct($name, $field = null, $shardSize = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setShardSize($shardSize);
+    }
+
+    /**
+     * @return int
+     */
+    public function getShardSize()
+    {
+        return $this->shardSize;
+    }
+
+    /**
+     * @param int $shardSize
+     */
+    public function setShardSize($shardSize)
+    {
+        $this->shardSize = $shardSize;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'sampler';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'field' => $this->getField(),
+                'shard_size' => $this->getShardSize(),
+            ]
+        );
+
+        return $out;
+    }
+}
diff --git a/src/Aggregation/Bucketing/SignificantTermsAggregation.php b/src/Aggregation/Bucketing/SignificantTermsAggregation.php
new file mode 100644
index 0000000..d3844de
--- /dev/null
+++ b/src/Aggregation/Bucketing/SignificantTermsAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+/**
+ * Class representing TermsAggregation.
+ *
+ * @link https://goo.gl/xI7zoa
+ */
+class SignificantTermsAggregation extends TermsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'significant_terms';
+    }
+}
diff --git a/src/Aggregation/Bucketing/TermsAggregation.php b/src/Aggregation/Bucketing/TermsAggregation.php
new file mode 100644
index 0000000..b1fe6c5
--- /dev/null
+++ b/src/Aggregation/Bucketing/TermsAggregation.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Bucketing;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing TermsAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-bucket-terms-aggregation.html
+ */
+class TermsAggregation extends AbstractAggregation
+{
+    use BucketingTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param string $script
+     */
+    public function __construct($name, $field = null, $script = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setScript($script);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'terms';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = array_filter(
+            [
+                'field' => $this->getField(),
+                'script' => $this->getScript(),
+            ]
+        );
+
+        return $data;
+    }
+}
diff --git a/src/Aggregation/CardinalityAggregation.php b/src/Aggregation/CardinalityAggregation.php
index 310ee73..67d3a11 100644
--- a/src/Aggregation/CardinalityAggregation.php
+++ b/src/Aggregation/CardinalityAggregation.php
@@ -11,102 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\CardinalityAggregation as Base;
 
 /**
  * Difference values counter.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class CardinalityAggregation extends AbstractAggregation
+class CardinalityAggregation extends Base
 {
-    use MetricTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * @var int
-     */
-    private $precisionThreshold;
-
-    /**
-     * @var bool
-     */
-    private $rehash;
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'field' => $this->getField(),
-                'script' => $this->getScript(),
-                'precision_threshold' => $this->getPrecisionThreshold(),
-                'rehash' => $this->isRehash(),
-            ],
-            function ($val) {
-                return ($val || is_bool($val));
-            }
-        );
-
-        $this->checkRequiredFields($out);
-
-        return $out;
-    }
-
-    /**
-     * Precision threshold.
-     *
-     * @param int $precision Precision Threshold.
-     */
-    public function setPrecisionThreshold($precision)
-    {
-        $this->precisionThreshold = $precision;
-    }
-
-    /**
-     * @return int
-     */
-    public function getPrecisionThreshold()
-    {
-        return $this->precisionThreshold;
-    }
-
-    /**
-     * @return bool
-     */
-    public function isRehash()
-    {
-        return $this->rehash;
-    }
-
-    /**
-     * @param bool $rehash
-     */
-    public function setRehash($rehash)
-    {
-        $this->rehash = $rehash;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'cardinality';
-    }
-
-    /**
-     * Checks if required fields are set.
-     *
-     * @param array $fields
-     *
-     * @throws \LogicException
-     */
-    private function checkRequiredFields($fields)
-    {
-        if (!array_key_exists('field', $fields) && !array_key_exists('script', $fields)) {
-            throw new \LogicException('Cardinality aggregation must have field or script set.');
-        }
-    }
 }
diff --git a/src/Aggregation/ChildrenAggregation.php b/src/Aggregation/ChildrenAggregation.php
index 6782ce8..503b32d 100644
--- a/src/Aggregation/ChildrenAggregation.php
+++ b/src/Aggregation/ChildrenAggregation.php
@@ -11,68 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\ChildrenAggregation as Base;
 
 /**
  * Class representing ChildrenAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class ChildrenAggregation extends AbstractAggregation
+class ChildrenAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var string
-     */
-    private $children;
-
-    /**
-     * Return children.
-     *
-     * @return string
-     */
-    public function getChildren()
-    {
-        return $this->children;
-    }
-
-    /**
-     * @param string $name
-     * @param string $children
-     */
-    public function __construct($name, $children = null)
-    {
-        parent::__construct($name);
-
-        $this->setChildren($children);
-    }
-
-    /**
-     * Sets children.
-     *
-     * @param string $children
-     */
-    public function setChildren($children)
-    {
-        $this->children = $children;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'children';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if (count($this->getAggregations()) == 0) {
-            throw new \LogicException("Children aggregation `{$this->getName()}` has no aggregations added");
-        }
-
-        return ['type' => $this->getChildren()];
-    }
 }
diff --git a/src/Aggregation/DateHistogramAggregation.php b/src/Aggregation/DateHistogramAggregation.php
index a78727d..10322a2 100644
--- a/src/Aggregation/DateHistogramAggregation.php
+++ b/src/Aggregation/DateHistogramAggregation.php
@@ -11,79 +11,16 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\DateHistogramAggregation as Base;
 
 /**
  * Class representing Histogram aggregation.
  *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
+ *
  * @link https://goo.gl/hGCdDd
  */
-class DateHistogramAggregation extends AbstractAggregation
+class DateHistogramAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var string
-     */
-    protected $interval;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param string $interval
-     */
-    public function __construct(
-        $name,
-        $field = null,
-        $interval = null
-    ) {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setInterval($interval);
-    }
-
-    /**
-     * @return int
-     */
-    public function getInterval()
-    {
-        return $this->interval;
-    }
-
-    /**
-     * @param string $interval
-     */
-    public function setInterval($interval)
-    {
-        $this->interval = $interval;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'date_histogram';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if (!$this->getField() || !$this->getInterval()) {
-            throw new \LogicException('Date histogram aggregation must have field and interval set.');
-        }
-
-        $out = [
-            'field' => $this->getField(),
-            'interval' => $this->getInterval(),
-        ];
-        $out = $this->processArray($out);
-
-        return $out;
-    }
 }
diff --git a/src/Aggregation/DateRangeAggregation.php b/src/Aggregation/DateRangeAggregation.php
index fb8f7e3..dea0bfa 100644
--- a/src/Aggregation/DateRangeAggregation.php
+++ b/src/Aggregation/DateRangeAggregation.php
@@ -11,110 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\DateRangeAggregation as Base;
 
 /**
  * Class representing date range aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class DateRangeAggregation extends AbstractAggregation
+class DateRangeAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var string
-     */
-    private $format;
-
-    /**
-     * @return string
-     */
-    public function getFormat()
-    {
-        return $this->format;
-    }
-
-    /**
-     * @param string $name
-     * @param string $field
-     * @param string $format
-     * @param array  $ranges
-     */
-    public function __construct($name, $field = null, $format = null, array $ranges = [])
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setFormat($format);
-        foreach ($ranges as $range) {
-            $from = isset($range['from']) ? $range['from'] : null;
-            $to = isset($range['to']) ? $range['to'] : null;
-            $this->addRange($from, $to);
-        }
-    }
-
-    /**
-     * @param string $format
-     */
-    public function setFormat($format)
-    {
-        $this->format = $format;
-    }
-
-    /**
-     * @var array
-     */
-    private $ranges = [];
-
-    /**
-     * Add range to aggregation.
-     *
-     * @param string|null $from
-     * @param string|null $to
-     *
-     * @return RangeAggregation
-     *
-     * @throws \LogicException
-     */
-    public function addRange($from = null, $to = null)
-    {
-        $range = array_filter(
-            [
-                'from' => $from,
-                'to' => $to,
-            ]
-        );
-
-        if (empty($range)) {
-            throw new \LogicException('Either from or to must be set. Both cannot be null.');
-        }
-
-        $this->ranges[] = $range;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if ($this->getField() && $this->getFormat() && !empty($this->ranges)) {
-            $data = [
-                'format' => $this->getFormat(),
-                'field' => $this->getField(),
-                'ranges' => $this->ranges,
-            ];
-
-            return $data;
-        }
-        throw new \LogicException('Date range aggregation must have field, format set and range added.');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'date_range';
-    }
 }
diff --git a/src/Aggregation/ExtendedStatsAggregation.php b/src/Aggregation/ExtendedStatsAggregation.php
index 45dcc67..a60980e 100644
--- a/src/Aggregation/ExtendedStatsAggregation.php
+++ b/src/Aggregation/ExtendedStatsAggregation.php
@@ -11,79 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\ExtendedStatsAggregation as Base;
 
 /**
  * Class representing Extended stats aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class ExtendedStatsAggregation extends AbstractAggregation
+class ExtendedStatsAggregation extends Base
 {
-    use MetricTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param int    $sigma
-     * @param string $script
-     */
-    public function __construct($name, $field = null, $sigma = null, $script = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setSigma($sigma);
-        $this->setScript($script);
-    }
-
-    /**
-     * @var int
-     */
-    private $sigma;
-
-    /**
-     * @return int
-     */
-    public function getSigma()
-    {
-        return $this->sigma;
-    }
-
-    /**
-     * @param int $sigma
-     */
-    public function setSigma($sigma)
-    {
-        $this->sigma = $sigma;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'extended_stats';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'field' => $this->getField(),
-                'script' => $this->getScript(),
-                'sigma' => $this->getSigma(),
-            ],
-            function ($val) {
-                return ($val || is_numeric($val));
-            }
-        );
-
-        return $out;
-    }
 }
diff --git a/src/Aggregation/FilterAggregation.php b/src/Aggregation/FilterAggregation.php
index 1782b46..f3ba4c6 100644
--- a/src/Aggregation/FilterAggregation.php
+++ b/src/Aggregation/FilterAggregation.php
@@ -11,71 +11,15 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
 use ONGR\ElasticsearchDSL\BuilderInterface;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\FilterAggregation as Base;
 
 /**
  * Class representing FilterAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class FilterAggregation extends AbstractAggregation
+class FilterAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var BuilderInterface
-     */
-    protected $filter;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string           $name
-     * @param BuilderInterface $filter
-     */
-    public function __construct($name, BuilderInterface $filter = null)
-    {
-        parent::__construct($name);
-
-        if ($filter !== null) {
-            $this->setFilter($filter);
-        }
-    }
-
-    /**
-     * Sets a filter.
-     *
-     * @param BuilderInterface $filter
-     */
-    public function setFilter(BuilderInterface $filter)
-    {
-        $this->filter = $filter;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setField($field)
-    {
-        throw new \LogicException("Filter aggregation, doesn't support `field` parameter");
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if (!$this->filter) {
-            throw new \LogicException("Filter aggregation `{$this->getName()}` has no filter added");
-        }
-
-        return $this->filter->toArray();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'filter';
-    }
 }
diff --git a/src/Aggregation/FiltersAggregation.php b/src/Aggregation/FiltersAggregation.php
index af8aa1a..733d948 100644
--- a/src/Aggregation/FiltersAggregation.php
+++ b/src/Aggregation/FiltersAggregation.php
@@ -11,93 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
-use ONGR\ElasticsearchDSL\BuilderInterface;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\FiltersAggregation as Base;
 
 /**
  * Class representing filters aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class FiltersAggregation extends AbstractAggregation
+class FiltersAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var BuilderInterface[]
-     */
-    private $filters = [];
-
-    /**
-     * @var bool
-     */
-    private $anonymous = false;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string             $name
-     * @param BuilderInterface[] $filters
-     * @param bool               $anonymous
-     */
-    public function __construct($name, $filters = [], $anonymous = false)
-    {
-        parent::__construct($name);
-
-        $this->setAnonymous($anonymous);
-        foreach ($filters as $name => $filter) {
-            if ($anonymous) {
-                $this->addFilter($filter);
-            } else {
-                $this->addFilter($filter, $name);
-            }
-        }
-    }
-
-    /**
-     * @param bool $anonymous
-     *
-     * @return FiltersAggregation
-     */
-    public function setAnonymous($anonymous)
-    {
-        $this->anonymous = $anonymous;
-
-        return $this;
-    }
-
-    /**
-     * @param BuilderInterface $filter
-     * @param string           $name
-     *
-     * @throws \LogicException
-     *
-     * @return FiltersAggregation
-     */
-    public function addFilter(BuilderInterface $filter, $name = '')
-    {
-        if ($this->anonymous === false && empty($name)) {
-            throw new \LogicException('In not anonymous filters filter name must be set.');
-        } elseif ($this->anonymous === false && !empty($name)) {
-            $this->filters['filters'][$name] = $filter->toArray();
-        } else {
-            $this->filters['filters'][] = $filter->toArray();
-        }
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        return $this->filters;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'filters';
-    }
 }
diff --git a/src/Aggregation/GeoBoundsAggregation.php b/src/Aggregation/GeoBoundsAggregation.php
index f408fba..17e02a4 100644
--- a/src/Aggregation/GeoBoundsAggregation.php
+++ b/src/Aggregation/GeoBoundsAggregation.php
@@ -11,73 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\GeoBoundsAggregation as Base;
 
 /**
  * Class representing geo bounds aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class GeoBoundsAggregation extends AbstractAggregation
+class GeoBoundsAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var bool
-     */
-    private $wrapLongitude = true;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param bool   $wrapLongitude
-     */
-    public function __construct($name, $field = null, $wrapLongitude = true)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setWrapLongitude($wrapLongitude);
-    }
-
-    /**
-     * @return bool
-     */
-    public function isWrapLongitude()
-    {
-        return $this->wrapLongitude;
-    }
-
-    /**
-     * @param bool $wrapLongitude
-     */
-    public function setWrapLongitude($wrapLongitude)
-    {
-        $this->wrapLongitude = $wrapLongitude;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = [];
-        if ($this->getField()) {
-            $data['field'] = $this->getField();
-        } else {
-            throw new \LogicException('Geo bounds aggregation must have a field set.');
-        }
-
-        $data['wrap_longitude'] = $this->isWrapLongitude();
-
-        return $data;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'geo_bounds';
-    }
 }
diff --git a/src/Aggregation/GeoCentroidAggregation.php b/src/Aggregation/GeoCentroidAggregation.php
index 51399c4..8995e8a 100644
--- a/src/Aggregation/GeoCentroidAggregation.php
+++ b/src/Aggregation/GeoCentroidAggregation.php
@@ -11,50 +11,16 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\GeoCentroidAggregation as Base;
 
 /**
  * Class representing geo centroid aggregation.
  *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
+ *
  * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-geocentroid-aggregation.html
  */
-class GeoCentroidAggregation extends AbstractAggregation
+class GeoCentroidAggregation extends Base
 {
-    use MetricTrait;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     */
-    public function __construct($name, $field = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = [];
-        if ($this->getField()) {
-            $data['field'] = $this->getField();
-        } else {
-            throw new \LogicException('Geo centroid aggregation must have a field set.');
-        }
-
-        return $data;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'geo_centroid';
-    }
 }
diff --git a/src/Aggregation/GeoDistanceAggregation.php b/src/Aggregation/GeoDistanceAggregation.php
index b9a0e6f..7281c30 100644
--- a/src/Aggregation/GeoDistanceAggregation.php
+++ b/src/Aggregation/GeoDistanceAggregation.php
@@ -11,173 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\GeoDistanceAggregation as Base;
 
 /**
  * Class representing geo distance aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class GeoDistanceAggregation extends AbstractAggregation
+class GeoDistanceAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var mixed
-     */
-    private $origin;
-
-    /**
-     * @var string
-     */
-    private $distanceType;
-
-    /**
-     * @var string
-     */
-    private $unit;
-
-    /**
-     * @var array
-     */
-    private $ranges = [];
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param mixed  $origin
-     * @param array  $ranges
-     * @param string $unit
-     * @param string $distanceType
-     */
-    public function __construct($name, $field = null, $origin = null, $ranges = [], $unit = null, $distanceType = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setOrigin($origin);
-        foreach ($ranges as $range) {
-            $from = isset($range['from']) ? $range['from'] : null;
-            $to = isset($range['to']) ? $range['to'] : null;
-            $this->addRange($from, $to);
-        }
-        $this->setUnit($unit);
-        $this->setDistanceType($distanceType);
-    }
-
-    /**
-     * @return string
-     */
-    public function getOrigin()
-    {
-        return $this->origin;
-    }
-
-    /**
-     * @param mixed $origin
-     */
-    public function setOrigin($origin)
-    {
-        $this->origin = $origin;
-    }
-
-    /**
-     * @return string
-     */
-    public function getDistanceType()
-    {
-        return $this->distanceType;
-    }
-
-    /**
-     * @param string $distanceType
-     */
-    public function setDistanceType($distanceType)
-    {
-        $this->distanceType = $distanceType;
-    }
-
-    /**
-     * @return string
-     */
-    public function getUnit()
-    {
-        return $this->unit;
-    }
-
-    /**
-     * @param string $unit
-     */
-    public function setUnit($unit)
-    {
-        $this->unit = $unit;
-    }
-
-    /**
-     * Add range to aggregation.
-     *
-     * @param int|float|null $from
-     * @param int|float|null $to
-     *
-     * @throws \LogicException
-     *
-     * @return GeoDistanceAggregation
-     */
-    public function addRange($from = null, $to = null)
-    {
-        $range = array_filter(
-            [
-                'from' => $from,
-                'to' => $to,
-            ]
-        );
-
-        if (empty($range)) {
-            throw new \LogicException('Either from or to must be set. Both cannot be null.');
-        }
-
-        $this->ranges[] = $range;
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = [];
-
-        if ($this->getField()) {
-            $data['field'] = $this->getField();
-        } else {
-            throw new \LogicException('Geo distance aggregation must have a field set.');
-        }
-
-        if ($this->getOrigin()) {
-            $data['origin'] = $this->getOrigin();
-        } else {
-            throw new \LogicException('Geo distance aggregation must have an origin set.');
-        }
-
-        if ($this->getUnit()) {
-            $data['unit'] = $this->getUnit();
-        }
-
-        if ($this->getDistanceType()) {
-            $data['distance_type'] = $this->getDistanceType();
-        }
-
-        $data['ranges'] = $this->ranges;
-
-        return $data;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'geo_distance';
-    }
 }
diff --git a/src/Aggregation/GeoHashGridAggregation.php b/src/Aggregation/GeoHashGridAggregation.php
index 875333d..b4132df 100644
--- a/src/Aggregation/GeoHashGridAggregation.php
+++ b/src/Aggregation/GeoHashGridAggregation.php
@@ -12,129 +12,14 @@
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
 use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\GeoHashGridAggregation as Base;
 
 /**
  * Class representing geohash grid aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class GeoHashGridAggregation extends AbstractAggregation
+class GeoHashGridAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var int
-     */
-    private $precision;
-
-    /**
-     * @var int
-     */
-    private $size;
-
-    /**
-     * @var int
-     */
-    private $shardSize;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param int    $precision
-     * @param int    $size
-     * @param int    $shardSize
-     */
-    public function __construct($name, $field = null, $precision = null, $size = null, $shardSize = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setPrecision($precision);
-        $this->setSize($size);
-        $this->setShardSize($shardSize);
-    }
-
-    /**
-     * @return int
-     */
-    public function getPrecision()
-    {
-        return $this->precision;
-    }
-
-    /**
-     * @param int $precision
-     */
-    public function setPrecision($precision)
-    {
-        $this->precision = $precision;
-    }
-
-    /**
-     * @return int
-     */
-    public function getSize()
-    {
-        return $this->size;
-    }
-
-    /**
-     * @param int $size
-     */
-    public function setSize($size)
-    {
-        $this->size = $size;
-    }
-
-    /**
-     * @return int
-     */
-    public function getShardSize()
-    {
-        return $this->shardSize;
-    }
-
-    /**
-     * @param int $shardSize
-     */
-    public function setShardSize($shardSize)
-    {
-        $this->shardSize = $shardSize;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = [];
-
-        if ($this->getField()) {
-            $data['field'] = $this->getField();
-        } else {
-            throw new \LogicException('Geo bounds aggregation must have a field set.');
-        }
-
-        if ($this->getPrecision()) {
-            $data['precision'] = $this->getPrecision();
-        }
-
-        if ($this->getSize()) {
-            $data['size'] = $this->getSize();
-        }
-
-        if ($this->getShardSize()) {
-            $data['shard_size'] = $this->getShardSize();
-        }
-
-        return $data;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'geohash_grid';
-    }
 }
diff --git a/src/Aggregation/GlobalAggregation.php b/src/Aggregation/GlobalAggregation.php
index ac48255..2eefcc5 100644
--- a/src/Aggregation/GlobalAggregation.php
+++ b/src/Aggregation/GlobalAggregation.php
@@ -11,36 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\GlobalAggregation as Base;
 
 /**
  * Class representing GlobalAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class GlobalAggregation extends AbstractAggregation
+class GlobalAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setField($field)
-    {
-        throw new \LogicException("Global aggregation, doesn't support `field` parameter");
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'global';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        return new \stdClass();
-    }
 }
diff --git a/src/Aggregation/HistogramAggregation.php b/src/Aggregation/HistogramAggregation.php
index 1d4bbbe..60d5188 100644
--- a/src/Aggregation/HistogramAggregation.php
+++ b/src/Aggregation/HistogramAggregation.php
@@ -11,224 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\HistogramAggregation as Base;
 
 /**
  * Class representing Histogram aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class HistogramAggregation extends AbstractAggregation
+class HistogramAggregation extends Base
 {
-    use BucketingTrait;
-
-    const DIRECTION_ASC = 'asc';
-    const DIRECTION_DESC = 'desc';
-
-    /**
-     * @var int
-     */
-    protected $interval;
-
-    /**
-     * @var int
-     */
-    protected $minDocCount;
-
-    /**
-     * @var array
-     */
-    protected $extendedBounds;
-
-    /**
-     * @var string
-     */
-    protected $orderMode;
-
-    /**
-     * @var string
-     */
-    protected $orderDirection;
-
-    /**
-     * @var bool
-     */
-    protected $keyed;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param int    $interval
-     * @param int    $minDocCount
-     * @param string $orderMode
-     * @param string $orderDirection
-     * @param int    $extendedBoundsMin
-     * @param int    $extendedBoundsMax
-     * @param bool   $keyed
-     */
-    public function __construct(
-        $name,
-        $field = null,
-        $interval = null,
-        $minDocCount = null,
-        $orderMode = null,
-        $orderDirection = self::DIRECTION_ASC,
-        $extendedBoundsMin = null,
-        $extendedBoundsMax = null,
-        $keyed = null
-    ) {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setInterval($interval);
-        $this->setMinDocCount($minDocCount);
-        $this->setOrder($orderMode, $orderDirection);
-        $this->setExtendedBounds($extendedBoundsMin, $extendedBoundsMax);
-        $this->setKeyed($keyed);
-    }
-
-    /**
-     * @return bool
-     */
-    public function isKeyed()
-    {
-        return $this->keyed;
-    }
-
-    /**
-     * Get response as a hash instead keyed by the buckets keys.
-     *
-     * @param bool $keyed
-     */
-    public function setKeyed($keyed)
-    {
-        $this->keyed = $keyed;
-    }
-
-    /**
-     * Sets buckets ordering.
-     *
-     * @param string $mode
-     * @param string $direction
-     */
-    public function setOrder($mode, $direction = self::DIRECTION_ASC)
-    {
-        $this->orderMode = $mode;
-        $this->orderDirection = $direction;
-    }
-
-    /**
-     * @return array
-     */
-    public function getOrder()
-    {
-        if ($this->orderMode && $this->orderDirection) {
-            return [$this->orderMode => $this->orderDirection];
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * @return int
-     */
-    public function getInterval()
-    {
-        return $this->interval;
-    }
-
-    /**
-     * @param int $interval
-     */
-    public function setInterval($interval)
-    {
-        $this->interval = $interval;
-    }
-
-    /**
-     * @return int
-     */
-    public function getMinDocCount()
-    {
-        return $this->minDocCount;
-    }
-
-    /**
-     * Set limit for document count buckets should have.
-     *
-     * @param int $minDocCount
-     */
-    public function setMinDocCount($minDocCount)
-    {
-        $this->minDocCount = $minDocCount;
-    }
-
-    /**
-     * @return array
-     */
-    public function getExtendedBounds()
-    {
-        return $this->extendedBounds;
-    }
-
-    /**
-     * @param int $min
-     * @param int $max
-     */
-    public function setExtendedBounds($min = null, $max = null)
-    {
-        $bounds = array_filter(
-            [
-                'min' => $min,
-                'max' => $max,
-            ]
-        );
-        $this->extendedBounds = $bounds;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'histogram';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'field' => $this->getField(),
-                'interval' => $this->getInterval(),
-                'min_doc_count' => $this->getMinDocCount(),
-                'extended_bounds' => $this->getExtendedBounds(),
-                'keyed' => $this->isKeyed(),
-                'order' => $this->getOrder(),
-            ],
-            function ($val) {
-                return ($val || is_numeric($val));
-            }
-        );
-        $this->checkRequiredParameters($out, ['field', 'interval']);
-
-        return $out;
-    }
-
-    /**
-     * Checks if all required parameters are set.
-     *
-     * @param array $data
-     * @param array $required
-     *
-     * @throws \LogicException
-     */
-    protected function checkRequiredParameters($data, $required)
-    {
-        if (count(array_intersect_key(array_flip($required), $data)) !== count($required)) {
-            throw new \LogicException('Histogram aggregation must have field and interval set.');
-        }
-    }
 }
diff --git a/src/Aggregation/Ipv4RangeAggregation.php b/src/Aggregation/Ipv4RangeAggregation.php
index 9b486b7..087c775 100644
--- a/src/Aggregation/Ipv4RangeAggregation.php
+++ b/src/Aggregation/Ipv4RangeAggregation.php
@@ -11,98 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\Ipv4RangeAggregation as Base;
 
 /**
  * Class representing ip range aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class Ipv4RangeAggregation extends AbstractAggregation
+class Ipv4RangeAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var array
-     */
-    private $ranges = [];
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param array  $ranges
-     */
-    public function __construct($name, $field = null, $ranges = [])
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        foreach ($ranges as $range) {
-            if (is_array($range)) {
-                $from = isset($range['from']) ? $range['from'] : null;
-                $to = isset($range['to']) ? $range['to'] : null;
-                $this->addRange($from, $to);
-            } else {
-                $this->addMask($range);
-            }
-        }
-    }
-
-    /**
-     * Add range to aggregation.
-     *
-     * @param string|null $from
-     * @param string|null $to
-     *
-     * @return Ipv4RangeAggregation
-     */
-    public function addRange($from = null, $to = null)
-    {
-        $range = array_filter(
-            [
-                'from' => $from,
-                'to' => $to,
-            ]
-        );
-
-        $this->ranges[] = $range;
-
-        return $this;
-    }
-
-    /**
-     * Add ip mask to aggregation.
-     *
-     * @param string $mask
-     *
-     * @return Ipv4RangeAggregation
-     */
-    public function addMask($mask)
-    {
-        $this->ranges[] = ['mask' => $mask];
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'ip_range';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if ($this->getField() && !empty($this->ranges)) {
-            return [
-                'field' => $this->getField(),
-                'ranges' => array_values($this->ranges),
-            ];
-        }
-        throw new \LogicException('Ip range aggregation must have field set and range added.');
-    }
 }
diff --git a/src/Aggregation/MaxAggregation.php b/src/Aggregation/MaxAggregation.php
index 406ece7..092ce7a 100644
--- a/src/Aggregation/MaxAggregation.php
+++ b/src/Aggregation/MaxAggregation.php
@@ -11,16 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Metric\MaxAggregation as Base;
+
 /**
  * Class representing Max Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class MaxAggregation extends StatsAggregation
+class MaxAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'max';
-    }
 }
diff --git a/src/Aggregation/Metric/AvgAggregation.php b/src/Aggregation/Metric/AvgAggregation.php
new file mode 100644
index 0000000..412c676
--- /dev/null
+++ b/src/Aggregation/Metric/AvgAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+/**
+ * Class representing Avg Aggregation.
+ *
+ * @link http://goo.gl/7KOIwo
+ */
+class AvgAggregation extends StatsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'avg';
+    }
+}
diff --git a/src/Aggregation/Metric/CardinalityAggregation.php b/src/Aggregation/Metric/CardinalityAggregation.php
new file mode 100644
index 0000000..1054787
--- /dev/null
+++ b/src/Aggregation/Metric/CardinalityAggregation.php
@@ -0,0 +1,115 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Difference values counter.
+ *
+ * @link http://goo.gl/tG7ciG
+ */
+class CardinalityAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * @var int
+     */
+    private $precisionThreshold;
+
+    /**
+     * @var bool
+     */
+    private $rehash;
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'field' => $this->getField(),
+                'script' => $this->getScript(),
+                'precision_threshold' => $this->getPrecisionThreshold(),
+                'rehash' => $this->isRehash(),
+            ],
+            function ($val) {
+                return ($val || is_bool($val));
+            }
+        );
+
+        $this->checkRequiredFields($out);
+
+        return $out;
+    }
+
+    /**
+     * Precision threshold.
+     *
+     * @param int $precision Precision Threshold.
+     */
+    public function setPrecisionThreshold($precision)
+    {
+        $this->precisionThreshold = $precision;
+    }
+
+    /**
+     * @return int
+     */
+    public function getPrecisionThreshold()
+    {
+        return $this->precisionThreshold;
+    }
+
+    /**
+     * @return bool
+     */
+    public function isRehash()
+    {
+        return $this->rehash;
+    }
+
+    /**
+     * @param bool $rehash
+     */
+    public function setRehash($rehash)
+    {
+        $this->rehash = $rehash;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'cardinality';
+    }
+
+    /**
+     * Checks if required fields are set.
+     *
+     * @param array $fields
+     *
+     * @throws \LogicException
+     */
+    private function checkRequiredFields($fields)
+    {
+        if (!array_key_exists('field', $fields) && !array_key_exists('script', $fields)) {
+            throw new \LogicException('Cardinality aggregation must have field or script set.');
+        }
+    }
+}
diff --git a/src/Aggregation/Metric/ExtendedStatsAggregation.php b/src/Aggregation/Metric/ExtendedStatsAggregation.php
new file mode 100644
index 0000000..4c5dac2
--- /dev/null
+++ b/src/Aggregation/Metric/ExtendedStatsAggregation.php
@@ -0,0 +1,92 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing Extended stats aggregation.
+ *
+ * @link http://goo.gl/E0PpDv
+ */
+class ExtendedStatsAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param int    $sigma
+     * @param string $script
+     */
+    public function __construct($name, $field = null, $sigma = null, $script = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setSigma($sigma);
+        $this->setScript($script);
+    }
+
+    /**
+     * @var int
+     */
+    private $sigma;
+
+    /**
+     * @return int
+     */
+    public function getSigma()
+    {
+        return $this->sigma;
+    }
+
+    /**
+     * @param int $sigma
+     */
+    public function setSigma($sigma)
+    {
+        $this->sigma = $sigma;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'extended_stats';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'field' => $this->getField(),
+                'script' => $this->getScript(),
+                'sigma' => $this->getSigma(),
+            ],
+            function ($val) {
+                return ($val || is_numeric($val));
+            }
+        );
+
+        return $out;
+    }
+}
diff --git a/src/Aggregation/Metric/GeoBoundsAggregation.php b/src/Aggregation/Metric/GeoBoundsAggregation.php
new file mode 100644
index 0000000..734f568
--- /dev/null
+++ b/src/Aggregation/Metric/GeoBoundsAggregation.php
@@ -0,0 +1,86 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+
+/**
+ * Class representing geo bounds aggregation.
+ *
+ * @link http://goo.gl/aGqw7Y
+ */
+class GeoBoundsAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+
+    /**
+     * @var bool
+     */
+    private $wrapLongitude = true;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param bool   $wrapLongitude
+     */
+    public function __construct($name, $field = null, $wrapLongitude = true)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setWrapLongitude($wrapLongitude);
+    }
+
+    /**
+     * @return bool
+     */
+    public function isWrapLongitude()
+    {
+        return $this->wrapLongitude;
+    }
+
+    /**
+     * @param bool $wrapLongitude
+     */
+    public function setWrapLongitude($wrapLongitude)
+    {
+        $this->wrapLongitude = $wrapLongitude;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = [];
+        if ($this->getField()) {
+            $data['field'] = $this->getField();
+        } else {
+            throw new \LogicException('Geo bounds aggregation must have a field set.');
+        }
+
+        $data['wrap_longitude'] = $this->isWrapLongitude();
+
+        return $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'geo_bounds';
+    }
+}
diff --git a/src/Aggregation/Metric/GeoCentroidAggregation.php b/src/Aggregation/Metric/GeoCentroidAggregation.php
new file mode 100644
index 0000000..807c81c
--- /dev/null
+++ b/src/Aggregation/Metric/GeoCentroidAggregation.php
@@ -0,0 +1,61 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+
+/**
+ * Class representing geo centroid aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-geocentroid-aggregation.html
+ */
+class GeoCentroidAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     */
+    public function __construct($name, $field = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $data = [];
+        if ($this->getField()) {
+            $data['field'] = $this->getField();
+        } else {
+            throw new \LogicException('Geo centroid aggregation must have a field set.');
+        }
+
+        return $data;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'geo_centroid';
+    }
+}
diff --git a/src/Aggregation/Metric/MaxAggregation.php b/src/Aggregation/Metric/MaxAggregation.php
new file mode 100644
index 0000000..7879e1d
--- /dev/null
+++ b/src/Aggregation/Metric/MaxAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+/**
+ * Class representing Max Aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-max-aggregation.html
+ */
+class MaxAggregation extends StatsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'max';
+    }
+}
diff --git a/src/Aggregation/Metric/MinAggregation.php b/src/Aggregation/Metric/MinAggregation.php
new file mode 100644
index 0000000..a92f943
--- /dev/null
+++ b/src/Aggregation/Metric/MinAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+/**
+ * Class representing Min Aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-min-aggregation.html
+ */
+class MinAggregation extends StatsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'min';
+    }
+}
diff --git a/src/Aggregation/Metric/PercentileRanksAggregation.php b/src/Aggregation/Metric/PercentileRanksAggregation.php
new file mode 100644
index 0000000..d335d99
--- /dev/null
+++ b/src/Aggregation/Metric/PercentileRanksAggregation.php
@@ -0,0 +1,134 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing Percentile Ranks Aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-rank-aggregation.html
+ */
+class PercentileRanksAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * @var array
+     */
+    private $values;
+
+    /**
+     * @var int
+     */
+    private $compression;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param array  $values
+     * @param string $script
+     * @param int    $compression
+     */
+    public function __construct($name, $field = null, $values = null, $script = null, $compression = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setValues($values);
+        $this->setScript($script);
+        $this->setCompression($compression);
+    }
+
+    /**
+     * @return array
+     */
+    public function getValues()
+    {
+        return $this->values;
+    }
+
+    /**
+     * @param array $values
+     */
+    public function setValues($values)
+    {
+        $this->values = $values;
+    }
+
+    /**
+     * @return int
+     */
+    public function getCompression()
+    {
+        return $this->compression;
+    }
+
+    /**
+     * @param int $compression
+     */
+    public function setCompression($compression)
+    {
+        $this->compression = $compression;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'percentile_ranks';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'field' => $this->getField(),
+                'script' => $this->getScript(),
+                'values' => $this->getValues(),
+                'compression' => $this->getCompression(),
+            ],
+            function ($val) {
+                return ($val || is_numeric($val));
+            }
+        );
+
+        $this->isRequiredParametersSet($out);
+
+        return $out;
+    }
+
+    /**
+     * @param array $a
+     *
+     * @return bool
+     * @throws \LogicException
+     */
+    private function isRequiredParametersSet($a)
+    {
+        if (array_key_exists('field', $a) && array_key_exists('values', $a)
+            || (array_key_exists('script', $a) && array_key_exists('values', $a))
+        ) {
+            return true;
+        }
+        throw new \LogicException('Percentile ranks aggregation must have field and values or script and values set.');
+    }
+}
diff --git a/src/Aggregation/Metric/PercentilesAggregation.php b/src/Aggregation/Metric/PercentilesAggregation.php
new file mode 100644
index 0000000..bb7c723
--- /dev/null
+++ b/src/Aggregation/Metric/PercentilesAggregation.php
@@ -0,0 +1,130 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing PercentilesAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html
+ */
+class PercentilesAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * @var array
+     */
+    private $percents;
+
+    /**
+     * @var int
+     */
+    private $compression;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param array  $percents
+     * @param string $script
+     * @param int    $compression
+     */
+    public function __construct($name, $field = null, $percents = null, $script = null, $compression = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setPercents($percents);
+        $this->setScript($script);
+        $this->setCompression($compression);
+    }
+
+    /**
+     * @return array
+     */
+    public function getPercents()
+    {
+        return $this->percents;
+    }
+
+    /**
+     * @param array $percents
+     */
+    public function setPercents($percents)
+    {
+        $this->percents = $percents;
+    }
+
+    /**
+     * @return int
+     */
+    public function getCompression()
+    {
+        return $this->compression;
+    }
+
+    /**
+     * @param int $compression
+     */
+    public function setCompression($compression)
+    {
+        $this->compression = $compression;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'percentiles';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'compression' => $this->getCompression(),
+                'percents' => $this->getPercents(),
+                'field' => $this->getField(),
+                'script' => $this->getScript(),
+            ],
+            function ($val) {
+                return ($val || is_numeric($val));
+            }
+        );
+
+        $this->isRequiredParametersSet($out);
+
+        return $out;
+    }
+
+    /**
+     * @param array $a
+     *
+     * @throws \LogicException
+     */
+    private function isRequiredParametersSet($a)
+    {
+        if (!array_key_exists('field', $a) && !array_key_exists('script', $a)) {
+            throw new \LogicException('Percentiles aggregation must have field or script set.');
+        }
+    }
+}
diff --git a/src/Aggregation/Metric/ScriptedMetricAggregation.php b/src/Aggregation/Metric/ScriptedMetricAggregation.php
new file mode 100644
index 0000000..4a0cea8
--- /dev/null
+++ b/src/Aggregation/Metric/ScriptedMetricAggregation.php
@@ -0,0 +1,158 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing StatsAggregation.
+ *
+ * @link http://goo.gl/JbQsI3
+ */
+class ScriptedMetricAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+
+    /**
+     * @var mixed
+     */
+    private $initScript;
+
+    /**
+     * @var mixed
+     */
+    private $mapScript;
+
+    /**
+     * @var mixed
+     */
+    private $combineScript;
+
+    /**
+     * @var mixed
+     */
+    private $reduceScript;
+    /**
+     * ScriptedMetricAggregation constructor.
+     * @param string $name
+     * @param mixed $initScript
+     * @param mixed $mapScript
+     * @param mixed $combineScript
+     * @param mixed $reduceScript
+     */
+    public function __construct(
+        $name,
+        $initScript = null,
+        $mapScript = null,
+        $combineScript = null,
+        $reduceScript = null
+    ) {
+    
+        parent::__construct($name);
+
+        $this->setInitScript($initScript);
+        $this->setMapScript($mapScript);
+        $this->setCombineScript($combineScript);
+        $this->setReduceScript($reduceScript);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'stats';
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getInitScript()
+    {
+        return $this->initScript;
+    }
+
+    /**
+     * @param mixed $initScript
+     */
+    public function setInitScript($initScript)
+    {
+        $this->initScript = $initScript;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getMapScript()
+    {
+        return $this->mapScript;
+    }
+
+    /**
+     * @param mixed $mapScript
+     */
+    public function setMapScript($mapScript)
+    {
+        $this->mapScript = $mapScript;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getCombineScript()
+    {
+        return $this->combineScript;
+    }
+
+    /**
+     * @param mixed $combineScript
+     */
+    public function setCombineScript($combineScript)
+    {
+        $this->combineScript = $combineScript;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getReduceScript()
+    {
+        return $this->reduceScript;
+    }
+
+    /**
+     * @param mixed $reduceScript
+     */
+    public function setReduceScript($reduceScript)
+    {
+        $this->reduceScript = $reduceScript;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = array_filter(
+            [
+                'init_script' => $this->getInitScript(),
+                'map_script' => $this->getMapScript(),
+                'combine_script' => $this->getCombineScript(),
+                'reduce_script' => $this->getReduceScript(),
+            ]
+        );
+
+        return $out;
+    }
+}
diff --git a/src/Aggregation/Metric/StatsAggregation.php b/src/Aggregation/Metric/StatsAggregation.php
new file mode 100644
index 0000000..c9fd2eb
--- /dev/null
+++ b/src/Aggregation/Metric/StatsAggregation.php
@@ -0,0 +1,66 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+
+/**
+ * Class representing StatsAggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-stats-aggregation.html
+ */
+class StatsAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+    use ScriptAwareTrait;
+
+    /**
+     * Inner aggregations container init.
+     *
+     * @param string $name
+     * @param string $field
+     * @param string $script
+     */
+    public function __construct($name, $field = null, $script = null)
+    {
+        parent::__construct($name);
+
+        $this->setField($field);
+        $this->setScript($script);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'stats';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $out = [];
+        if ($this->getField()) {
+            $out['field'] = $this->getField();
+        }
+        if ($this->getScript()) {
+            $out['script'] = $this->getScript();
+        }
+
+        return $out;
+    }
+}
diff --git a/src/Aggregation/Metric/SumAggregation.php b/src/Aggregation/Metric/SumAggregation.php
new file mode 100644
index 0000000..ba2ddbc
--- /dev/null
+++ b/src/Aggregation/Metric/SumAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+/**
+ * Class representing Sum Aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html
+ */
+class SumAggregation extends StatsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'sum';
+    }
+}
diff --git a/src/Aggregation/Metric/TopHitsAggregation.php b/src/Aggregation/Metric/TopHitsAggregation.php
new file mode 100644
index 0000000..b8dab96
--- /dev/null
+++ b/src/Aggregation/Metric/TopHitsAggregation.php
@@ -0,0 +1,146 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+use ONGR\ElasticsearchDSL\Aggregation\AbstractAggregation;
+use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
+use ONGR\ElasticsearchDSL\BuilderInterface;
+
+/**
+ * Top hits aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-top-hits-aggregation.html
+ */
+class TopHitsAggregation extends AbstractAggregation
+{
+    use MetricTrait;
+
+    /**
+     * @var int Number of top matching hits to return per bucket.
+     */
+    private $size;
+
+    /**
+     * @var int The offset from the first result you want to fetch.
+     */
+    private $from;
+
+    /**
+     * @var BuilderInterface How the top matching hits should be sorted.
+     */
+    private $sort;
+
+    /**
+     * Constructor for top hits.
+     *
+     * @param string                $name Aggregation name.
+     * @param null|int              $size Number of top matching hits to return per bucket.
+     * @param null|int              $from The offset from the first result you want to fetch.
+     * @param null|BuilderInterface $sort How the top matching hits should be sorted.
+     */
+    public function __construct($name, $size = null, $from = null, $sort = null)
+    {
+        parent::__construct($name);
+        $this->setFrom($from);
+        $this->setSize($size);
+        $this->setSort($sort);
+    }
+
+    /**
+     * Return from.
+     *
+     * @return int
+     */
+    public function getFrom()
+    {
+        return $this->from;
+    }
+
+    /**
+     * Set from.
+     *
+     * @param int $from
+     */
+    public function setFrom($from)
+    {
+        $this->from = $from;
+    }
+
+    /**
+     * Return sort.
+     *
+     * @return BuilderInterface
+     */
+    public function getSort()
+    {
+        return $this->sort;
+    }
+
+    /**
+     * Set sort.
+     *
+     * @param BuilderInterface $sort
+     */
+    public function setSort($sort)
+    {
+        $this->sort = $sort;
+    }
+
+    /**
+     * Set size.
+     *
+     * @param int $size
+     */
+    public function setSize($size)
+    {
+        $this->size = $size;
+    }
+
+    /**
+     * Return size.
+     *
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'top_hits';
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getArray()
+    {
+        $output = array_filter(
+            [
+                'sort' => $this->getSort() ? $this->getSort()->toArray() : null,
+                'size' => $this->getSize(),
+                'from' => $this->getFrom(),
+            ],
+            function ($val) {
+                return (($val || is_array($val) || ($val || is_numeric($val))));
+            }
+        );
+
+        $output = $this->processArray($output);
+
+        return empty($output) ? new \stdClass() : $output;
+    }
+}
diff --git a/src/Aggregation/Metric/ValueCountAggregation.php b/src/Aggregation/Metric/ValueCountAggregation.php
new file mode 100644
index 0000000..617a966
--- /dev/null
+++ b/src/Aggregation/Metric/ValueCountAggregation.php
@@ -0,0 +1,28 @@
+<?php
+
+/*
+ * This file is part of the ONGR package.
+ *
+ * (c) NFQ Technologies UAB <info@nfq.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace ONGR\ElasticsearchDSL\Aggregation\Metric;
+
+/**
+ * Class representing Value Count Aggregation.
+ *
+ * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-valuecount-aggregation.html
+ */
+class ValueCountAggregation extends StatsAggregation
+{
+    /**
+     * {@inheritdoc}
+     */
+    public function getType()
+    {
+        return 'value_count';
+    }
+}
diff --git a/src/Aggregation/MinAggregation.php b/src/Aggregation/MinAggregation.php
index 3fe8f4b..dee6e3f 100644
--- a/src/Aggregation/MinAggregation.php
+++ b/src/Aggregation/MinAggregation.php
@@ -11,16 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Metric\MinAggregation as Base;
+
 /**
  * Class representing Min Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class MinAggregation extends StatsAggregation
+class MinAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'min';
-    }
 }
diff --git a/src/Aggregation/MissingAggregation.php b/src/Aggregation/MissingAggregation.php
index 5330289..4937c67 100644
--- a/src/Aggregation/MissingAggregation.php
+++ b/src/Aggregation/MissingAggregation.php
@@ -11,44 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\MissingAggregation as Base;
 
 /**
  * Class representing missing aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class MissingAggregation extends AbstractAggregation
+class MissingAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     */
-    public function __construct($name, $field = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if ($this->getField()) {
-            return ['field' => $this->getField()];
-        }
-        throw new \LogicException('Missing aggregation must have a field set.');
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'missing';
-    }
 }
diff --git a/src/Aggregation/NestedAggregation.php b/src/Aggregation/NestedAggregation.php
index be5da0b..dd5951c 100644
--- a/src/Aggregation/NestedAggregation.php
+++ b/src/Aggregation/NestedAggregation.php
@@ -11,66 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\NestedAggregation as Base;
 
 /**
  * Class representing NestedAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class NestedAggregation extends AbstractAggregation
+class NestedAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var string
-     */
-    private $path;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $path
-     */
-    public function __construct($name, $path = null)
-    {
-        parent::__construct($name);
-
-        $this->setPath($path);
-    }
-
-    /**
-     * Return path.
-     *
-     * @return string
-     */
-    public function getPath()
-    {
-        return $this->path;
-    }
-
-    /**
-     * Sets path.
-     *
-     * @param string $path
-     */
-    public function setPath($path)
-    {
-        $this->path = $path;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'nested';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        return ['path' => $this->getPath()];
-    }
 }
diff --git a/src/Aggregation/PercentileRanksAggregation.php b/src/Aggregation/PercentileRanksAggregation.php
index 20f839e..4de6dd1 100644
--- a/src/Aggregation/PercentileRanksAggregation.php
+++ b/src/Aggregation/PercentileRanksAggregation.php
@@ -11,121 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\PercentileRanksAggregation as Base;
 
 /**
  * Class representing Percentile Ranks Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class PercentileRanksAggregation extends AbstractAggregation
+class PercentileRanksAggregation extends Base
 {
-    use MetricTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * @var array
-     */
-    private $values;
-
-    /**
-     * @var int
-     */
-    private $compression;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param array  $values
-     * @param string $script
-     * @param int    $compression
-     */
-    public function __construct($name, $field = null, $values = null, $script = null, $compression = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setValues($values);
-        $this->setScript($script);
-        $this->setCompression($compression);
-    }
-
-    /**
-     * @return array
-     */
-    public function getValues()
-    {
-        return $this->values;
-    }
-
-    /**
-     * @param array $values
-     */
-    public function setValues($values)
-    {
-        $this->values = $values;
-    }
-
-    /**
-     * @return int
-     */
-    public function getCompression()
-    {
-        return $this->compression;
-    }
-
-    /**
-     * @param int $compression
-     */
-    public function setCompression($compression)
-    {
-        $this->compression = $compression;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'percentile_ranks';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'field' => $this->getField(),
-                'script' => $this->getScript(),
-                'values' => $this->getValues(),
-                'compression' => $this->getCompression(),
-            ],
-            function ($val) {
-                return ($val || is_numeric($val));
-            }
-        );
-
-        $this->isRequiredParametersSet($out);
-
-        return $out;
-    }
-
-    /**
-     * @param array $a
-     *
-     * @return bool
-     * @throws \LogicException
-     */
-    private function isRequiredParametersSet($a)
-    {
-        if (array_key_exists('field', $a) && array_key_exists('values', $a)
-            || (array_key_exists('script', $a) && array_key_exists('values', $a))
-        ) {
-            return true;
-        }
-        throw new \LogicException('Percentile ranks aggregation must have field and values or script and values set.');
-    }
 }
diff --git a/src/Aggregation/PercentilesAggregation.php b/src/Aggregation/PercentilesAggregation.php
index 3f203c4..bc3f03c 100644
--- a/src/Aggregation/PercentilesAggregation.php
+++ b/src/Aggregation/PercentilesAggregation.php
@@ -11,117 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\PercentilesAggregation as Base;
 
 /**
  * Class representing PercentilesAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class PercentilesAggregation extends AbstractAggregation
+class PercentilesAggregation extends Base
 {
-    use MetricTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * @var array
-     */
-    private $percents;
-
-    /**
-     * @var int
-     */
-    private $compression;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param array  $percents
-     * @param string $script
-     * @param int    $compression
-     */
-    public function __construct($name, $field = null, $percents = null, $script = null, $compression = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setPercents($percents);
-        $this->setScript($script);
-        $this->setCompression($compression);
-    }
-
-    /**
-     * @return array
-     */
-    public function getPercents()
-    {
-        return $this->percents;
-    }
-
-    /**
-     * @param array $percents
-     */
-    public function setPercents($percents)
-    {
-        $this->percents = $percents;
-    }
-
-    /**
-     * @return int
-     */
-    public function getCompression()
-    {
-        return $this->compression;
-    }
-
-    /**
-     * @param int $compression
-     */
-    public function setCompression($compression)
-    {
-        $this->compression = $compression;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'percentiles';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'compression' => $this->getCompression(),
-                'percents' => $this->getPercents(),
-                'field' => $this->getField(),
-                'script' => $this->getScript(),
-            ],
-            function ($val) {
-                return ($val || is_numeric($val));
-            }
-        );
-
-        $this->isRequiredParametersSet($out);
-
-        return $out;
-    }
-
-    /**
-     * @param array $a
-     *
-     * @throws \LogicException
-     */
-    private function isRequiredParametersSet($a)
-    {
-        if (!array_key_exists('field', $a) && !array_key_exists('script', $a)) {
-            throw new \LogicException('Percentiles aggregation must have field or script set.');
-        }
-    }
 }
diff --git a/src/Aggregation/RangeAggregation.php b/src/Aggregation/RangeAggregation.php
index 557e9c4..de7d375 100644
--- a/src/Aggregation/RangeAggregation.php
+++ b/src/Aggregation/RangeAggregation.php
@@ -11,153 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\RangeAggregation as Base;
 
 /**
  * Class representing RangeAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class RangeAggregation extends AbstractAggregation
+class RangeAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var array
-     */
-    private $ranges = [];
-
-    /**
-     * @var bool
-     */
-    private $keyed = false;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param array  $ranges
-     * @param bool   $keyed
-     */
-    public function __construct($name, $field = null, $ranges = [], $keyed = false)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setKeyed($keyed);
-        foreach ($ranges as $range) {
-            $from = isset($range['from']) ? $range['from'] : null;
-            $to = isset($range['to']) ? $range['to'] : null;
-            $key = isset($range['key']) ? $range['key'] : null;
-            $this->addRange($from, $to, $key);
-        }
-    }
-
-    /**
-     * Sets if result buckets should be keyed.
-     *
-     * @param bool $keyed
-     *
-     * @return RangeAggregation
-     */
-    public function setKeyed($keyed)
-    {
-        $this->keyed = $keyed;
-
-        return $this;
-    }
-
-    /**
-     * Add range to aggregation.
-     *
-     * @param int|float|null $from
-     * @param int|float|null $to
-     * @param string         $key
-     *
-     * @return RangeAggregation
-     */
-    public function addRange($from = null, $to = null, $key = '')
-    {
-        $range = array_filter(
-            [
-                'from' => $from,
-                'to' => $to,
-            ]
-        );
-
-        if ($this->keyed && !empty($key)) {
-            $range['key'] = $key;
-        }
-
-        $this->ranges[] = $range;
-
-        return $this;
-    }
-
-    /**
-     * Remove range from aggregation. Returns true on success.
-     *
-     * @param int|float|null $from
-     * @param int|float|null $to
-     *
-     * @return bool
-     */
-    public function removeRange($from, $to)
-    {
-        foreach ($this->ranges as $key => $range) {
-            if (array_diff_assoc(array_filter(['from' => $from, 'to' => $to]), $range) === []) {
-                unset($this->ranges[$key]);
-
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * Removes range by key.
-     *
-     * @param string $key Range key.
-     *
-     * @return bool
-     */
-    public function removeRangeByKey($key)
-    {
-        if ($this->keyed) {
-            foreach ($this->ranges as $rangeKey => $range) {
-                if (array_key_exists('key', $range) && $range['key'] === $key) {
-                    unset($this->ranges[$rangeKey]);
-
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = [
-            'keyed' => $this->keyed,
-            'ranges' => array_values($this->ranges),
-        ];
-
-        if ($this->getField()) {
-            $data['field'] = $this->getField();
-        }
-
-        return $data;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'range';
-    }
 }
diff --git a/src/Aggregation/ReverseNestedAggregation.php b/src/Aggregation/ReverseNestedAggregation.php
index 55b58b2..6dc112b 100644
--- a/src/Aggregation/ReverseNestedAggregation.php
+++ b/src/Aggregation/ReverseNestedAggregation.php
@@ -11,75 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\ReverseNestedAggregation as Base;
 
 /**
  * Class representing ReverseNestedAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class ReverseNestedAggregation extends AbstractAggregation
+class ReverseNestedAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * @var string
-     */
-    private $path;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $path
-     */
-    public function __construct($name, $path = null)
-    {
-        parent::__construct($name);
-
-        $this->setPath($path);
-    }
-
-    /**
-     * Return path.
-     *
-     * @return string
-     */
-    public function getPath()
-    {
-        return $this->path;
-    }
-
-    /**
-     * Sets path.
-     *
-     * @param string $path
-     */
-    public function setPath($path)
-    {
-        $this->path = $path;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'reverse_nested';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        if (count($this->getAggregations()) == 0) {
-            throw new \LogicException("Reverse Nested aggregation `{$this->getName()}` has no aggregations added");
-        }
-
-        $output = new \stdClass();
-        if ($this->getPath()) {
-            $output = ['path' => $this->getPath()];
-        }
-
-        return $output;
-    }
 }
diff --git a/src/Aggregation/SamplerAggregation.php b/src/Aggregation/SamplerAggregation.php
index 64fd182..f7534d3 100644
--- a/src/Aggregation/SamplerAggregation.php
+++ b/src/Aggregation/SamplerAggregation.php
@@ -11,77 +11,16 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\SamplerAggregation as Base;
 
 /**
  * Class representing geo bounds aggregation.
  *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
+ *
  * @link https://www.elastic.co/guide/en/elasticsearch/reference/2.3/search-aggregations-bucket-sampler-aggregation.html
  */
-class SamplerAggregation extends AbstractAggregation
+class SamplerAggregation extends Base
 {
-    use BucketingTrait;
-
-    /**
-     * Defines how many results will be received from each shard
-     * @param string $shardSize
-     */
-    private $shardSize;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param int    $shardSize
-     */
-    public function __construct(
-        $name,
-        $field = null,
-        $shardSize = null
-    ) {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setShardSize($shardSize);
-    }
-
-    /**
-     * @return int
-     */
-    public function getShardSize()
-    {
-        return $this->shardSize;
-    }
-
-    /**
-     * @param int $shardSize
-     */
-    public function setShardSize($shardSize)
-    {
-        $this->shardSize = $shardSize;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'sampler';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = array_filter(
-            [
-                'field' => $this->getField(),
-                'shard_size' => $this->getShardSize(),
-            ]
-        );
-
-        return $out;
-    }
 }
diff --git a/src/Aggregation/SignificantTermsAggregation.php b/src/Aggregation/SignificantTermsAggregation.php
index 7fef119..0852cd2 100644
--- a/src/Aggregation/SignificantTermsAggregation.php
+++ b/src/Aggregation/SignificantTermsAggregation.php
@@ -11,18 +11,16 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\SignificantTermsAggregation as Base;
+
 /**
  * Class representing TermsAggregation.
  *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
+ *
  * @link https://goo.gl/xI7zoa
  */
-class SignificantTermsAggregation extends TermsAggregation
+class SignificantTermsAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'significant_terms';
-    }
 }
diff --git a/src/Aggregation/StatsAggregation.php b/src/Aggregation/StatsAggregation.php
index 425bea5..a3fccfd 100644
--- a/src/Aggregation/StatsAggregation.php
+++ b/src/Aggregation/StatsAggregation.php
@@ -11,53 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\StatsAggregation as Base;
 
 /**
  * Class representing StatsAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class StatsAggregation extends AbstractAggregation
+class StatsAggregation extends Base
 {
-    use MetricTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param string $script
-     */
-    public function __construct($name, $field = null, $script = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setScript($script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'stats';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $out = [];
-        if ($this->getField()) {
-            $out['field'] = $this->getField();
-        }
-        if ($this->getScript()) {
-            $out['script'] = $this->getScript();
-        }
-
-        return $out;
-    }
 }
diff --git a/src/Aggregation/SumAggregation.php b/src/Aggregation/SumAggregation.php
index 0552b32..93ff1d6 100644
--- a/src/Aggregation/SumAggregation.php
+++ b/src/Aggregation/SumAggregation.php
@@ -11,16 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Metric\SumAggregation as Base;
+
 /**
  * Class representing Sum Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class SumAggregation extends StatsAggregation
+class SumAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'sum';
-    }
 }
diff --git a/src/Aggregation/TermsAggregation.php b/src/Aggregation/TermsAggregation.php
index 2b65ec1..e07fcf0 100644
--- a/src/Aggregation/TermsAggregation.php
+++ b/src/Aggregation/TermsAggregation.php
@@ -11,52 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
-use ONGR\ElasticsearchDSL\Aggregation\Type\BucketingTrait;
-use ONGR\ElasticsearchDSL\ScriptAwareTrait;
+use ONGR\ElasticsearchDSL\Aggregation\Bucketing\TermsAggregation as Base;
 
 /**
  * Class representing TermsAggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class TermsAggregation extends AbstractAggregation
+class TermsAggregation extends Base
 {
-    use BucketingTrait;
-    use ScriptAwareTrait;
-
-    /**
-     * Inner aggregations container init.
-     *
-     * @param string $name
-     * @param string $field
-     * @param string $script
-     */
-    public function __construct($name, $field = null, $script = null)
-    {
-        parent::__construct($name);
-
-        $this->setField($field);
-        $this->setScript($script);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'terms';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $data = array_filter(
-            [
-                'field' => $this->getField(),
-                'script' => $this->getScript(),
-            ]
-        );
-
-        return $data;
-    }
 }
diff --git a/src/Aggregation/TopHitsAggregation.php b/src/Aggregation/TopHitsAggregation.php
index e88e996..222c320 100644
--- a/src/Aggregation/TopHitsAggregation.php
+++ b/src/Aggregation/TopHitsAggregation.php
@@ -13,131 +13,14 @@ namespace ONGR\ElasticsearchDSL\Aggregation;
 
 use ONGR\ElasticsearchDSL\Aggregation\Type\MetricTrait;
 use ONGR\ElasticsearchDSL\BuilderInterface;
+use ONGR\ElasticsearchDSL\Aggregation\Metric\TopHitsAggregation as Base;
 
 /**
  * Top hits aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class TopHitsAggregation extends AbstractAggregation
+class TopHitsAggregation extends Base
 {
-    use MetricTrait;
-
-    /**
-     * @var int Number of top matching hits to return per bucket.
-     */
-    private $size;
-
-    /**
-     * @var int The offset from the first result you want to fetch.
-     */
-    private $from;
-
-    /**
-     * @var BuilderInterface How the top matching hits should be sorted.
-     */
-    private $sort;
-
-    /**
-     * Constructor for top hits.
-     *
-     * @param string                $name Aggregation name.
-     * @param null|int              $size Number of top matching hits to return per bucket.
-     * @param null|int              $from The offset from the first result you want to fetch.
-     * @param null|BuilderInterface $sort How the top matching hits should be sorted.
-     */
-    public function __construct($name, $size = null, $from = null, $sort = null)
-    {
-        parent::__construct($name);
-        $this->setFrom($from);
-        $this->setSize($size);
-        $this->setSort($sort);
-    }
-
-    /**
-     * Return from.
-     *
-     * @return int
-     */
-    public function getFrom()
-    {
-        return $this->from;
-    }
-
-    /**
-     * Set from.
-     *
-     * @param int $from
-     */
-    public function setFrom($from)
-    {
-        $this->from = $from;
-    }
-
-    /**
-     * Return sort.
-     *
-     * @return BuilderInterface
-     */
-    public function getSort()
-    {
-        return $this->sort;
-    }
-
-    /**
-     * Set sort.
-     *
-     * @param BuilderInterface $sort
-     */
-    public function setSort($sort)
-    {
-        $this->sort = $sort;
-    }
-
-    /**
-     * Set size.
-     *
-     * @param int $size
-     */
-    public function setSize($size)
-    {
-        $this->size = $size;
-    }
-
-    /**
-     * Return size.
-     *
-     * @return int
-     */
-    public function getSize()
-    {
-        return $this->size;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'top_hits';
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getArray()
-    {
-        $output = array_filter(
-            [
-                'sort' => $this->getSort() ? $this->getSort()->toArray() : null,
-                'size' => $this->getSize(),
-                'from' => $this->getFrom(),
-            ],
-            function ($val) {
-                return (($val || is_array($val) || ($val || is_numeric($val))));
-            }
-        );
-
-        $output = $this->processArray($output);
-
-        return empty($output) ? new \stdClass() : $output;
-    }
 }
diff --git a/src/Aggregation/ValueCountAggregation.php b/src/Aggregation/ValueCountAggregation.php
index 07286e6..6ae7b61 100644
--- a/src/Aggregation/ValueCountAggregation.php
+++ b/src/Aggregation/ValueCountAggregation.php
@@ -11,16 +11,14 @@
 
 namespace ONGR\ElasticsearchDSL\Aggregation;
 
+use ONGR\ElasticsearchDSL\Aggregation\Metric\ValueCountAggregation as Base;
+
 /**
  * Class representing Value Count Aggregation.
+ *
+ * @deprecated Aggregations was moved to it's type namespace. Add `Metric` or `Bucketing` after `Aggregation`.
+ *     This class will be removed in 3.0.
  */
-class ValueCountAggregation extends StatsAggregation
+class ValueCountAggregation extends Base
 {
-    /**
-     * {@inheritdoc}
-     */
-    public function getType()
-    {
-        return 'value_count';
-    }
 }
diff --git a/src/SearchEndpoint/InnerHitsEndpoint.php b/src/SearchEndpoint/InnerHitsEndpoint.php
index b3d4213..f1562fe 100644
--- a/src/SearchEndpoint/InnerHitsEndpoint.php
+++ b/src/SearchEndpoint/InnerHitsEndpoint.php
@@ -11,7 +11,7 @@
 
 namespace ONGR\ElasticsearchDSL\SearchEndpoint;
 
-use ONGR\ElasticsearchDSL\InnerHit\AbstractInnerHit;
+use ONGR\ElasticsearchDSL\InnerHit\NestedInnerHit;
 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 
 /**
@@ -31,7 +31,7 @@ class InnerHitsEndpoint extends AbstractSearchEndpoint
     {
         $output = [];
         if (count($this->getAll()) > 0) {
-            /** @var AbstractInnerHit $innerHit */
+            /** @var NestedInnerHit $innerHit */
             foreach ($this->getAll() as $innerHit) {
                 $output[$innerHit->getName()] = $innerHit->toArray();
             }
-- 
GitLab