diff --git a/src/SearchEndpoint/AbstractSearchEndpoint.php b/src/SearchEndpoint/AbstractSearchEndpoint.php
index 0480223785811dfca8e47e66f20c8722906e71c0..d6bdc9662604c6eb16309df078de5db533ecbc87 100644
--- a/src/SearchEndpoint/AbstractSearchEndpoint.php
+++ b/src/SearchEndpoint/AbstractSearchEndpoint.php
@@ -11,6 +11,8 @@
 
 namespace ONGR\ElasticsearchDSL\SearchEndpoint;
 
+use ONGR\ElasticsearchDSL\BuilderInterface;
+use ONGR\ElasticsearchDSL\ParametersTrait;
 use ONGR\ElasticsearchDSL\Serializer\Normalizer\AbstractNormalizable;
 
 /**
@@ -18,5 +20,79 @@ use ONGR\ElasticsearchDSL\Serializer\Normalizer\AbstractNormalizable;
  */
 abstract class AbstractSearchEndpoint extends AbstractNormalizable implements SearchEndpointInterface
 {
-    use BuilderContainerAwareTrait;
+    use ParametersTrait;
+
+    /**
+     * @var BuilderInterface[]
+     */
+    private $container = [];
+
+    /**
+     * {@inheritdoc}
+     */
+    public function add(BuilderInterface $builder, $key = null)
+    {
+        if (array_key_exists($key, $this->container)) {
+            throw new \OverflowException(sprintf('Builder with %s name for endpoint has already been added!', $key));
+        }
+
+        if (!$key) {
+            $key = uniqid();
+        }
+
+        $this->container[$key] = $builder;
+
+        return $key;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function addToBool(BuilderInterface $builder, $boolType = null, $key = null)
+    {
+        throw new \BadFunctionCallException(sprintf("Endpoint %s doesn't support bool statements", static::NAME));
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function remove($key)
+    {
+        if ($this->has($key)) {
+            unset($this->container[$key]);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Checks if builder with specific key exists.
+     *
+     * @param $key
+     * @return bool
+     */
+    public function has($key)
+    {
+        return array_key_exists($key, $this->container);
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function get($key)
+    {
+        if ($this->has($key)) {
+            return $this->container[$key];
+        }
+
+        return null;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getAll($boolType = null)
+    {
+        return $this->container;
+    }
 }
diff --git a/src/SearchEndpoint/AggregationsEndpoint.php b/src/SearchEndpoint/AggregationsEndpoint.php
index e9f9ae7e7d8c0ab4ea75cc41b426c0c94d0b61e7..444066df949ed2ef3274a7611535cb175870fdf7 100644
--- a/src/SearchEndpoint/AggregationsEndpoint.php
+++ b/src/SearchEndpoint/AggregationsEndpoint.php
@@ -11,84 +11,31 @@
 
 namespace ONGR\ElasticsearchDSL\SearchEndpoint;
 
-use ONGR\ElasticsearchDSL\BuilderInterface;
-use ONGR\ElasticsearchDSL\NamedBuilderBag;
-use ONGR\ElasticsearchDSL\NamedBuilderInterface;
+use ONGR\ElasticsearchDSL\BuilderBag;
 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 
 /**
  * Search aggregations dsl endpoint.
  */
-class AggregationsEndpoint implements SearchEndpointInterface
+class AggregationsEndpoint extends AbstractSearchEndpoint
 {
-    use BuilderContainerAwareTrait;
-
     /**
-     * @var NamedBuilderBag
+     * Endpoint name
      */
-    private $bag;
-
-    /**
-     * Initialized aggregations bag.
-     */
-    public function __construct()
-    {
-        $this->bag = new NamedBuilderBag();
-    }
+    CONST NAME = 'aggregations';
 
     /**
      * {@inheritdoc}
      */
     public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
-        if (count($this->bag->all()) > 0) {
-            return $this->bag->toArray();
-        }
-
-        return null;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function addBuilder(BuilderInterface $builder, $parameters = [])
-    {
-        if (!($builder instanceof NamedBuilderInterface)) {
-            throw new \InvalidArgumentException('Builder must be named builder');
-        }
-
-        $this->bag->add($builder);
-
-        return $builder->getName();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getBuilders()
-    {
-        return $this->bag->all();
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getBuilder($key)
-    {
-        if (!$this->bag->has($key)) {
-            return null;
+        if (count($this->getAll()) > 0) {
+            $output = [];
+            foreach ($this->getAll() as $aggregation) {
+                $output[] = $aggregation->toArray();
+            }
         }
 
-        return $this->bag->get($key);
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function removeBuilder($key)
-    {
-        $this->bag->remove($key);
-
-        return $this;
+        return $output;
     }
 }
diff --git a/src/SearchEndpoint/BuilderContainerAwareTrait.php b/src/SearchEndpoint/BuilderContainerAwareTrait.php
deleted file mode 100644
index d6b3aa6e7cd8c781e9e670c69fc401734e352189..0000000000000000000000000000000000000000
--- a/src/SearchEndpoint/BuilderContainerAwareTrait.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?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\SearchEndpoint;
-
-use ONGR\ElasticsearchDSL\BuilderInterface;
-
-/**
- * Trait to implement SearchEndpointInterface builder methods.
- */
-trait BuilderContainerAwareTrait
-{
-    /**
-     * @var BuilderInterface[]
-     */
-    private $builderContainer = [];
-
-    /**
-     * @var array
-     */
-    private $parameterContainer = [];
-
-    /**
-     * {@inheritdoc}
-     */
-    public function addBuilder(BuilderInterface $builder, $parameters = [])
-    {
-        $this->builderContainer[] = $builder;
-        end($this->builderContainer);
-        $key = key($this->builderContainer);
-
-        $this->parameterContainer[$key] = $parameters;
-
-        return $key;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function removeBuilder($key)
-    {
-        if (array_key_exists($key, $this->builderContainer)) {
-            unset($this->builderContainer[$key]);
-            unset($this->parameterContainer[$key]);
-        }
-
-        return $this;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getBuilder($key)
-    {
-        if (array_key_exists($key, $this->builderContainer)) {
-            return $this->builderContainer[$key];
-        }
-
-        return null;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getBuilders()
-    {
-        return $this->builderContainer;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function getBuilderParameters($key)
-    {
-        if (array_key_exists($key, $this->parameterContainer)) {
-            return $this->parameterContainer[$key];
-        }
-
-        return [];
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function setBuilderParameters($key, $parameters)
-    {
-        $this->parameterContainer[$key] = $parameters;
-
-        return $this;
-    }
-}
diff --git a/src/SearchEndpoint/FilterEndpoint.php b/src/SearchEndpoint/FilterEndpoint.php
index 1e375095c3156b80b1ebcb30b6b50fc1b5c2e070..ef53e00d82ee63dc9d75218c8e87adae1c78e0f9 100644
--- a/src/SearchEndpoint/FilterEndpoint.php
+++ b/src/SearchEndpoint/FilterEndpoint.php
@@ -20,18 +20,29 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
  */
 class FilterEndpoint extends QueryEndpoint
 {
+    /**
+     * Endpoint name
+     */
+    CONST NAME = 'filter';
+
     /**
      * {@inheritdoc}
      */
     public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
-        $builder = $this->getBuilderForNormalization();
-        if (empty($builder)) {
-            return;
+        if (!$this->getBool()) {
+            return null;
         }
 
         $query = new FilteredQuery();
-        $query->setFilter($builder);
+        if ($this->getBool()->isRelevant()) {
+            $filters = $this->getBool()->getQueries(BoolFilter::MUST);
+            $filter = array_shift($filters);
+        } else {
+            $filter = $this->getBool();
+        }
+
+        $query->setFilter($filter);
         $this->addReference('filtered_query', $query);
     }
 
@@ -44,7 +55,9 @@ class FilterEndpoint extends QueryEndpoint
     }
 
     /**
-     * {@inheritdoc}
+     * Returns bool instance for this endpoint case.
+     *
+     * @return BoolFilter
      */
     protected function getBoolInstance()
     {
diff --git a/src/SearchEndpoint/HighlightEndpoint.php b/src/SearchEndpoint/HighlightEndpoint.php
index ddc61199a2449ce3b67d7e81f2ae7d9520c16e2c..c0d16a584f3b7ef7570c9daacdb7c9267ea52156 100644
--- a/src/SearchEndpoint/HighlightEndpoint.php
+++ b/src/SearchEndpoint/HighlightEndpoint.php
@@ -17,14 +17,15 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 /**
  * Search highlight dsl endpoint.
  */
-class HighlightEndpoint implements SearchEndpointInterface
+class HighlightEndpoint extends AbstractSearchEndpoint
 {
-    use BuilderContainerAwareTrait {
-        addBuilder as private traitAddBuilder;
-    }
+    /**
+     * Endpoint name
+     */
+    CONST NAME = 'highlight';
 
     /**
-     * @var int
+     * @var BuilderInterface
      */
     private $highlight;
 
@@ -33,24 +34,22 @@ class HighlightEndpoint implements SearchEndpointInterface
      */
     public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
-        if (!$this->getBuilder($this->highlight)) {
-            return null;
+        if ($this->highlight) {
+            return $this->highlight->toArray();
         }
 
-        return $this->getBuilder($this->highlight)->toArray();
+        return null;
     }
 
     /**
      * {@inheritdoc}
      */
-    public function addBuilder(BuilderInterface $builder, $parameters = [])
+    public function add(BuilderInterface $builder, $key = null)
     {
-        if ($this->getBuilders()) {
-            throw new \OverflowException('Only one highlight is expected');
+        if ($this->highlight) {
+            throw new \OverflowException('Only one highlight can be set');
         }
 
-        $this->highlight = $this->traitAddBuilder($builder, $parameters);
-
-        return $this->highlight;
+        $this->highlight = $builder;
     }
 }
diff --git a/src/SearchEndpoint/PostFilterEndpoint.php b/src/SearchEndpoint/PostFilterEndpoint.php
index 50e2fb7b9f2e6bc7da24e76f1c51361b029b2a26..88bfc57f5c179d4365461a65ede2bdb52e88fd83 100644
--- a/src/SearchEndpoint/PostFilterEndpoint.php
+++ b/src/SearchEndpoint/PostFilterEndpoint.php
@@ -11,7 +11,7 @@
 
 namespace ONGR\ElasticsearchDSL\SearchEndpoint;
 
-use ONGR\ElasticsearchDSL\Filter\PostFilter;
+use ONGR\ElasticsearchDSL\Filter\BoolFilter;
 use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 
 /**
@@ -19,20 +19,35 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
  */
 class PostFilterEndpoint extends FilterEndpoint
 {
+    /**
+     * Endpoint name
+     */
+    CONST NAME = 'post_filter';
+
     /**
      * {@inheritdoc}
      */
     public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
-        $builder = $this->getBuilderForNormalization();
-
-        if (empty($builder)) {
+        if (!$this->getBool()) {
             return null;
         }
 
-        $postFilter = new PostFilter();
-        $postFilter->setFilter($builder);
+        if ($this->getBool()->isRelevant()) {
+            $filters = $this->getBool()->getQueries(BoolFilter::MUST);
+            $filter = array_shift($filters);
+        } else {
+            $filter = $this->getBool();
+        }
 
-        return $postFilter->toArray();
+        return [$filter->getType() => $filter->toArray()];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getOrder()
+    {
+        return 2;
     }
 }
diff --git a/src/SearchEndpoint/QueryEndpoint.php b/src/SearchEndpoint/QueryEndpoint.php
index b8d2da882e4b8882e3c5f6c394605d1e23d202d2..1c4c83e08d29222fb669281783c0406a1e232df6 100644
--- a/src/SearchEndpoint/QueryEndpoint.php
+++ b/src/SearchEndpoint/QueryEndpoint.php
@@ -25,21 +25,15 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
  */
 class QueryEndpoint extends AbstractSearchEndpoint implements OrderedNormalizerInterface
 {
-    use ParametersTrait;
-
     /**
-     * @var OptionsResolver
+     * Endpoint name
      */
-    private $resolver;
+    CONST NAME = 'query';
 
     /**
-     * Instantiates resolver.
+     * @var BoolQuery
      */
-    public function __construct()
-    {
-        $this->resolver = new OptionsResolver();
-        $this->configureResolver($this->resolver);
-    }
+    private $bool;
 
     /**
      * {@inheritdoc}
@@ -47,90 +41,67 @@ class QueryEndpoint extends AbstractSearchEndpoint implements OrderedNormalizerI
     public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
         if ($this->hasReference('filtered_query')) {
-            /** @var FilteredQuery $query */
-            $query = $this->getReference('filtered_query');
-            $this->addBuilder($query);
+            /** @var FilteredQuery $filteredQuery */
+            $filteredQuery = $this->getReference('filtered_query');
+            $this->add($filteredQuery);
         }
 
-        $builder = $this->getBuilderForNormalization();
-
-        if (empty($builder)) {
+        if (!$this->bool) {
             return null;
         }
 
-        return [$builder->getType() => $builder->toArray()];
+        $queryArray = $this->bool->toArray();
+
+        if (!$this->bool->isRelevant()) {
+            $queryArray = [$this->bool->getType() => $queryArray];
+        }
+
+        return $queryArray;
     }
 
     /**
-     * Return builder that is ready to be normalized.
-     *
-     * @return BuilderInterface|null
+     * {@inheritdoc}
      */
-    protected function getBuilderForNormalization()
+    public function add(BuilderInterface $builder, $key = null)
     {
-        $builders = $this->getbuilders();
-        if (empty($builders)) {
-            return null;
-        }
-
-        if (count($builders) > 1) {
-            $builder = $this->buildBool();
-        } else {
-            $builder = end($builders);
-        }
-
-        if (method_exists($builder, 'setParameters') && count($this->getParameters()) > 0) {
-            $builder->setParameters($this->processArray($builder->getParameters()));
-        }
-
-        return $builder;
+        return $this->addToBool($builder, BoolQuery::MUST, $key);
     }
 
     /**
      * {@inheritdoc}
      */
-    public function getOrder()
+    public function addToBool(BuilderInterface $builder, $boolType = null, $key = null)
     {
-        return 2;
+        if (!$this->bool) {
+            $this->bool = $this->createBoolInstance();
+        }
+
+        $this->bool->add($builder, $boolType, $key);
     }
 
     /**
-     * Default properties for query.
-     *
-     * @param OptionsResolver $resolver
+     * {@inheritdoc}
      */
-    protected function configureResolver(OptionsResolver $resolver)
+    public function getOrder()
     {
-        $resolver
-            ->setDefaults(
-                ['bool_type' => BoolQuery::MUST]
-            );
+        return 3;
     }
 
     /**
-     * Returns bool instance for this endpoint case.
-     *
-     * @return BoolFilter|BoolQuery
+     * @return BoolQuery
      */
-    protected function getBoolInstance()
+    public function getBool()
     {
-        return new BoolQuery();
+        return $this->bool;
     }
 
     /**
-     * Returns bool instance with builders set.
+     * Returns new bool instance for the endpoint.
      *
-     * @return BoolFilter|BoolQuery
+     * @return BoolQuery
      */
-    protected function buildBool()
+    protected function createBoolInstance()
     {
-        $boolInstance = $this->getBoolInstance();
-
-        foreach ($this->getBuilders() as $key => $builder) {
-            $parameters = $this->resolver->resolve(array_filter($this->getBuilderParameters($key)));
-            $boolInstance->add($builder, $parameters['bool_type']);
-        }
-
-        return $boolInstance;
+        return new BoolQuery();
     }
 }
diff --git a/src/SearchEndpoint/SearchEndpointInterface.php b/src/SearchEndpoint/SearchEndpointInterface.php
index 1f04cea444d92c2500751da47f9640dfa25c36b6..13991125fab1c4fda8c5b24a18809336b34fd9f4 100644
--- a/src/SearchEndpoint/SearchEndpointInterface.php
+++ b/src/SearchEndpoint/SearchEndpointInterface.php
@@ -12,6 +12,7 @@
 namespace ONGR\ElasticsearchDSL\SearchEndpoint;
 
 use ONGR\ElasticsearchDSL\BuilderInterface;
+use ONGR\ElasticsearchDSL\Query\BoolQuery;
 use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
 
 /**
@@ -23,11 +24,23 @@ interface SearchEndpointInterface extends NormalizableInterface
      * Adds builder to search endpoint.
      *
      * @param BuilderInterface $builder    Builder to add.
-     * @param array            $parameters Additional parameters relevant to builder.
+     * @param array            $key        Additional parameters relevant to builder.
      *
-     * @return int Returns builder key.
+     * @return string Key of added builder.
      */
-    public function addBuilder(BuilderInterface $builder, $parameters = []);
+    public function add(BuilderInterface $builder, $key = null);
+
+    /**
+     * Adds builder to search endpoint's specific bool type container.
+     *
+     * @param BuilderInterface $builder    Builder to add.
+     * @param array            $boolType   Bool type for query or filter. If bool type is left null
+     *                                         it will be treated as MUST.
+     * @param array            $key        Additional parameters relevant to builder.
+     *
+     * @return string Key of added builder.
+     */
+    public function addToBool(BuilderInterface $builder, $boolType = null, $key = null);
 
     /**
      * Removes contained builder.
@@ -36,7 +49,7 @@ interface SearchEndpointInterface extends NormalizableInterface
      *
      * @return $this
      */
-    public function removeBuilder($key);
+    public function remove($key);
 
     /**
      * Returns contained builder or null if Builder is not found.
@@ -45,29 +58,14 @@ interface SearchEndpointInterface extends NormalizableInterface
      *
      * @return BuilderInterface|null
      */
-    public function getBuilder($key);
+    public function get($key);
 
     /**
-     * Returns all contained builders.
-     *
-     * @return BuilderInterface[]
-     */
-    public function getBuilders();
-
-    /**
-     * Returns parameters for contained builder or empty array if parameters are not found.
+     * Returns contained builder or null if Builder is not found.
      *
-     * @param int $key
+     * @param string|null $boolType If bool type is left null it will return all builders from container.
      *
      * @return array
      */
-    public function getBuilderParameters($key);
-
-    /**
-     * @param int   $key
-     * @param array $parameters
-     *
-     * @return $this
-     */
-    public function setBuilderParameters($key, $parameters);
+    public function getAll($boolType = null);
 }
diff --git a/src/SearchEndpoint/SortEndpoint.php b/src/SearchEndpoint/SortEndpoint.php
index 7c14cc76c24cc6ff3507fa9c1142d888da47e4e6..13eaf6a828bbaa52dd6576bd3f950c6456b34546 100644
--- a/src/SearchEndpoint/SortEndpoint.php
+++ b/src/SearchEndpoint/SortEndpoint.php
@@ -19,51 +19,24 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
 /**
  * Search sort dsl endpoint.
  */
-class SortEndpoint implements SearchEndpointInterface
+class SortEndpoint extends AbstractSearchEndpoint
 {
-    use BuilderContainerAwareTrait {
-        addBuilder as private traitAddBuilder;
-    }
-
-    /**
-     * {@inheritdoc}
-     */
-    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
-    {
-        $sorts = $this->buildSorts();
-
-        if ($sorts->isRelevant()) {
-            return $sorts->toArray();
-        }
-
-        return null;
-    }
-
     /**
-     * Builds sorts object.
-     *
-     * @return Sorts
+     * Endpoint name
      */
-    protected function buildSorts()
-    {
-        $sorts = new Sorts();
-        /** @var AbstractSort $builder */
-        foreach ($this->getBuilders() as $builder) {
-            $sorts->addSort($builder);
-        }
-
-        return $sorts;
-    }
+    CONST NAME = 'sort';
 
     /**
      * {@inheritdoc}
      */
-    public function addBuilder(BuilderInterface $builder, $parameters = [])
+    public function normalize(NormalizerInterface $normalizer, $format = null, array $context = [])
     {
-        if (!($builder instanceof AbstractSort)) {
-            throw new \InvalidArgumentException('Sort must must a subtype of AbstractSort');
+        $output = [];
+
+        foreach($this->getAll() as $sort) {
+            $output[] = $sort->toArray();
         }
 
-        return $this->traitAddBuilder($builder, $parameters);
+        return $output;
     }
 }