diff --git a/README.md b/README.md index 6f14ff9..14b8f7b 100644 --- a/README.md +++ b/README.md @@ -26,19 +26,20 @@ class MoviesFrom2014Query extends AbstractQuery { $this->searchIn('movies', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - 'term' => array( - 'year' => 2014 - ) - ) - ) - ) - ); - + // Full notation + $body = [ + 'query' => [ + 'filtered' => [ + 'filter' => [ + 'term' => ['year' => 2014] + ] + ] + ] + ]; $this->setBody($body); + + // Short (dotted) notation + $this->set('query.filtered.filter.term.year', 2014); } } @@ -58,17 +59,7 @@ class MoviesFrom2014Query extends AbstractQuery { $this->searchIn('movies', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - new YearFilter(2014) - ) - ) - ) - ); - - $this->setBody($body); + $this->set('query.filtered.filter', [new YearFilter(2014)]); } } ``` diff --git a/docs/index-management.md b/docs/index-management.md index 63809b9..606e567 100644 --- a/docs/index-management.md +++ b/docs/index-management.md @@ -1,7 +1,7 @@ # Index Management The package includes an indices manager. You are required to register indices that you'll using, whether its for -CRUD on the indices or for quering. The index manager is accessed via: +CRUD on the indices or for querying. The index manager is accessed via: ```php $manager = $searcher->indicesManager(); @@ -20,33 +20,28 @@ class SuggestionsIndex extends \ElasticSearcher\Abstracts\AbstractIndex return 'suggestions'; } - public function getTypes() + public function setup() { - return array( - 'books' => array( - 'properties' => array( - 'id' => array( - 'type' => 'integer' - ), - 'name' => array( - 'type' => 'string' - ) - ) - ), - 'movies' => array( - 'properties' => array( - 'name' => array( - 'type' => 'string' - ) - ) - ) - ); + $this->setTypes([ + 'books' => [ + 'properties' => [ + 'id' => ['type' => 'integer'], + 'name' => ['type' => 'string'], + ] + ], + 'movies' => [ + 'properties' => [ + 'name' => ['type' => 'string'], + ] + ] + ]); } } ``` -This the minimum required for defining an index. If you require more extensive configuration, override the `getBody` -method. +This the minimum required for defining an index. Inside the `setup()` method you can setup your index further, +for example adding settings, aggregations, .... An index is [body aware](https://github.com/madewithlove/elasticsearcher/tree/master/src/Traits/BodyTrait.php) +for easy manipulation. ### Using re-useable fragments @@ -65,9 +60,9 @@ $suggestionsIndex = new SuggestionsIndex(); $searcher->indicesManager()->register($suggestionsIndex); // Grouped registration -$indices = array( +$indices = [ $suggestionsIndex -); +]; $searcher->indicesManager()->registerIndices($indices); // Other diff --git a/docs/query-building.md b/docs/query-building.md index bcb007c..1765cab 100644 --- a/docs/query-building.md +++ b/docs/query-building.md @@ -31,8 +31,9 @@ var_dump($result->getResults()); ## Body building -Inside your Query class you can build the body of the query however you like. We only require you to call `setBody` with -the body array. Here are some examples. +Inside your Query class you can build the body of the query however you like. A query is +[body aware](https://github.com/madewithlove/elasticsearcher/tree/master/src/Traits/BodyTrait.php) +for easy manipulation. Here are some examples. Basic example: @@ -45,19 +46,20 @@ class MoviesYouMightLikeQuery extends QueryAbstract { $this->searchIn('suggestions', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - 'term' => array( - 'status' => 'active' - ) - ) - ) - ) - ); - - $this->setBody($body); + // Long notation + $body = [ + 'query' => [ + 'filtered' => [ + 'filter' => [ + 'term' => ['status' => 'active'] + ] + ] + ] + ]; + $this->setBody($body); + + // Short dotted notation + $this->set('query.filtered.filter.term.status', 'active'); } } ``` @@ -73,19 +75,7 @@ class MoviesYouMightLikeQuery extends AbstractQuery { $this->searchIn('suggestions', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - 'term' => array( - 'status' => $this->getData('status') - ) - ) - ) - ) - ); - - $this->setBody($body); + $this->set('query.filtered.filter.term.status', $this->getData('status')); } } ``` diff --git a/docs/re-useable-fragments.md b/docs/re-useable-fragments.md index 2d2b7c2..5fc136f 100644 --- a/docs/re-useable-fragments.md +++ b/docs/re-useable-fragments.md @@ -5,6 +5,9 @@ comes with a build-in set of fragments but you are encouraged to build your own. For example: `BookingRangeFilter(date, date)`, `MovieIDFilter(int)`, .... As long as they extend `ElasticSearcher\Abstracts\AbstractFragment` they can be used in queries or indices. +A fragment is [body aware](https://github.com/madewithlove/elasticsearcher/tree/master/src/Traits/BodyTrait.php) +for easy manipulation. + ## Examples ```php diff --git a/src/Abstracts/AbstractFragment.php b/src/Abstracts/AbstractFragment.php index ef8cdc7..9661839 100644 --- a/src/Abstracts/AbstractFragment.php +++ b/src/Abstracts/AbstractFragment.php @@ -2,18 +2,14 @@ namespace ElasticSearcher\Abstracts; +use ElasticSearcher\Traits\BodyTrait; + /** * Base class for fragments that can be used in the body of requests to Elasticsearch. */ abstract class AbstractFragment { - /** - * Body of the fragment to be executed. Should be the array as if you would pass it - * directly to the ElasticSearcher SDK. - * - * @var array - */ - protected $body; + use BodyTrait; /** * Should this fragment be merged with its parent, or simply be replaced. @@ -23,20 +19,4 @@ abstract class AbstractFragment * @var bool */ public $mergeWithParent = false; - - /** - * @param array $body - */ - public function setBody(array $body) - { - $this->body = $body; - } - - /** - * @return array - */ - public function getBody() - { - return $this->body; - } } diff --git a/src/Abstracts/AbstractIndex.php b/src/Abstracts/AbstractIndex.php index d35ac1c..6d10c72 100644 --- a/src/Abstracts/AbstractIndex.php +++ b/src/Abstracts/AbstractIndex.php @@ -3,12 +3,15 @@ namespace ElasticSearcher\Abstracts; use ElasticSearcher\Parsers\FragmentParser; +use ElasticSearcher\Traits\BodyTrait; /** * Base class for indexes. */ abstract class AbstractIndex { + use BodyTrait; + /** * @var FragmentParser */ @@ -22,13 +25,15 @@ abstract public function getName(); /** * @return array */ - abstract public function getTypes(); + abstract public function setup(); /** */ public function __construct() { $this->fragmentParser = new FragmentParser(); + + $this->setup(); } /** @@ -36,15 +41,36 @@ public function __construct() */ public function getBody() { - $body = [ - 'settings' => $this->getSettings(), - 'mappings' => $this->getTypes(), - ]; - // Replace fragments with their raw body. - $body = $this->fragmentParser->parse($body); + return $this->fragmentParser->parse($this->body); + } + + /** + * @param array $types + * + * @return array + */ + public function setTypes(array $types) + { + return $this->set('mappings', $types); + } + + /** + * @return array + */ + public function getTypes() + { + return $this->get('mappings'); + } - return $body; + /** + * @param array $settings + * + * @return array + */ + public function setSettings(array $settings) + { + return $this->set('settings', $settings); } /** @@ -52,18 +78,16 @@ public function getBody() */ public function getSettings() { - return null; + return $this->get('settings'); } /** * @param string $type * - * @return mixed + * @return array */ public function getType($type) { - $types = $this->getTypes(); - - return $types[$type]; + return $this->get('mappings.'.$type); } } diff --git a/src/Abstracts/AbstractQuery.php b/src/Abstracts/AbstractQuery.php index 41772c5..c681acc 100644 --- a/src/Abstracts/AbstractQuery.php +++ b/src/Abstracts/AbstractQuery.php @@ -5,12 +5,15 @@ use ElasticSearcher\ElasticSearcher; use ElasticSearcher\Parsers\ArrayResultParser; use ElasticSearcher\Parsers\FragmentParser; +use ElasticSearcher\Traits\BodyTrait; /** * Base class for queries. */ abstract class AbstractQuery { + use BodyTrait; + /** * @var ElasticSearcher */ @@ -30,13 +33,6 @@ abstract class AbstractQuery */ protected $types = []; - /** - * Body of the query to execute. - * - * @var array - */ - protected $body = []; - /** * Data that can be used when building a query. * @@ -142,14 +138,6 @@ protected function searchInTypes(array $types) $this->types = array_unique($this->types); } - /** - * @param array $body - */ - protected function setBody(array $body) - { - $this->body = $body; - } - /** * Build the query by adding all chunks together. * diff --git a/src/Traits/BodyTrait.php b/src/Traits/BodyTrait.php new file mode 100644 index 0000000..ceabc58 --- /dev/null +++ b/src/Traits/BodyTrait.php @@ -0,0 +1,66 @@ +body = $body; + } + + /** + * @return array + */ + public function getBody() + { + return $this->body; + } + + /** + * Set a value in the body using the dotted notation. + * + * @param string $key + * @param mixed $value + * + * @return $this + */ + public function set($key, $value) + { + Arr::set($this->body, $key, $value); + + return $this; + } + + /** + * Get a value in the body using the dotted notation. + * + * @param string $key + * @param mixed $default + * + * @return $this + */ + public function get($key, $default = null) + { + return Arr::get($this->body, $key, $default); + } +} diff --git a/tests/Traits/BodyTraitTest.php b/tests/Traits/BodyTraitTest.php new file mode 100644 index 0000000..ebe17c9 --- /dev/null +++ b/tests/Traits/BodyTraitTest.php @@ -0,0 +1,17 @@ +getMockForTrait(BodyTrait::class); + + $mock->set('key', 'value'); + $this->assertEquals(['key' => 'value'], $mock->getBody()); + + $mock->set('key.nested', 'value'); + $this->assertEquals(['key' => ['nested' => 'value']], $mock->getBody()); + } +} diff --git a/tests/dummy/Indexes/AuthorsIndex.php b/tests/dummy/Indexes/AuthorsIndex.php index 5859e03..ac2dc2f 100644 --- a/tests/dummy/Indexes/AuthorsIndex.php +++ b/tests/dummy/Indexes/AuthorsIndex.php @@ -9,32 +9,22 @@ public function getName() return 'authors'; } - public function getTypes() + public function setup() { - return array( - 'directors' => array( - 'properties' => array( - 'id' => array( - 'type' => 'integer' - ), - 'first_name' => array( - 'type' => 'string' - ), - 'last_name' => array( - 'type' => 'string' - ) - ) - ), - 'producers' => array( - 'properties' => array( - 'id' => array( - 'type' => 'integer' - ), - 'name' => array( - 'type' => 'string' - ) - ) - ) - ); + $this->setTypes([ + 'directors' => [ + 'properties' => [ + 'id' => ['type' => 'integer'], + 'first_name' => ['type' => 'string'], + 'last_name' => ['type' => 'string'] + ] + ], + 'producers' => [ + 'properties' => [ + 'id' => ['type' => 'integer'], + 'name' => ['type' => 'string'] + ] + ] + ]); } } diff --git a/tests/dummy/Indexes/MoviesIndex.php b/tests/dummy/Indexes/MoviesIndex.php index bc26ceb..a59573a 100644 --- a/tests/dummy/Indexes/MoviesIndex.php +++ b/tests/dummy/Indexes/MoviesIndex.php @@ -9,22 +9,16 @@ public function getName() return 'movies'; } - public function getTypes() + public function setup() { - return array( - 'movies' => array( - 'properties' => array( - 'id' => array( - 'type' => 'integer' - ), - 'name' => array( - 'type' => 'string' - ), - 'year' => array( - 'type' => 'integer', - ) - ) - ) - ); + $this->setTypes([ + 'movies' => [ + 'properties' => [ + 'id' => ['type' => 'integer'], + 'name' => ['type' => 'string'], + 'year' => ['type' => 'integer'], + ] + ] + ]); } } diff --git a/tests/dummy/Queries/MovieWithIDXQuery.php b/tests/dummy/Queries/MovieWithIDXQuery.php index c6e0aa4..453c644 100644 --- a/tests/dummy/Queries/MovieWithIDXQuery.php +++ b/tests/dummy/Queries/MovieWithIDXQuery.php @@ -8,16 +8,6 @@ public function setup() { $this->searchIn('movies', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - new IDFilter($this->getData('id')) - ) - ) - ) - ); - - $this->setBody($body); + $this->set('query.filtered.filter', [new IDFilter($this->getData('id'))]); } } diff --git a/tests/dummy/Queries/MoviesFrom2014Query.php b/tests/dummy/Queries/MoviesFrom2014Query.php index 1f1a034..aa4cacd 100644 --- a/tests/dummy/Queries/MoviesFrom2014Query.php +++ b/tests/dummy/Queries/MoviesFrom2014Query.php @@ -9,16 +9,6 @@ public function setup() { $this->searchIn('movies', 'movies'); - $body = array( - 'query' => array( - 'filtered' => array( - 'filter' => array( - new TermFilter('year', 2014) - ) - ) - ) - ); - - $this->setBody($body); + $this->set('query.filtered.filter', [new TermFilter('year', 2014)]); } }