From d08ebde5a0a23ffbf837a9e661c757e1989c003b Mon Sep 17 00:00:00 2001 From: asim-byng Date: Wed, 10 Aug 2016 15:05:12 +0100 Subject: [PATCH] Added a raw gateway to allow any query to any index --- .../Elasticsearch/ElasticsearchPlugin.php | 7 +- .../Elasticsearch/Gateway/RawGateway.php | 145 ++++++++++++++++++ .../Gateway/RawGatewayFactory.php | 40 +++++ .../Elasticsearch/Query/QueryBuilder.php | 126 +++++++++++++++ 4 files changed, 317 insertions(+), 1 deletion(-) create mode 100644 lib/Byng/Pimcore/Elasticsearch/Gateway/RawGateway.php create mode 100644 lib/Byng/Pimcore/Elasticsearch/Gateway/RawGatewayFactory.php diff --git a/lib/Byng/Pimcore/Elasticsearch/ElasticsearchPlugin.php b/lib/Byng/Pimcore/Elasticsearch/ElasticsearchPlugin.php index 42ae6e3..e5c6f66 100644 --- a/lib/Byng/Pimcore/Elasticsearch/ElasticsearchPlugin.php +++ b/lib/Byng/Pimcore/Elasticsearch/ElasticsearchPlugin.php @@ -21,6 +21,7 @@ use Byng\Pimcore\Elasticsearch\PluginConfig\ConfigDistFilePath; use Byng\Pimcore\Elasticsearch\PluginConfig\ConfigFilePath; use Byng\Pimcore\Elasticsearch\Gateway\PageGatewayFactory; +use Byng\Pimcore\Elasticsearch\Gateway\RawGatewayFactory; use Byng\Pimcore\Elasticsearch\PluginConfig\ConfigSchemaPath; use Elasticsearch\ClientBuilder; use Pimcore; @@ -35,6 +36,7 @@ * @author Elliot Wright * @author Matt Ward * @author Michal Maszkiewicz + * @author Asim Liaquat */ final class ElasticsearchPlugin extends AbstractPlugin implements PluginInterface { @@ -44,9 +46,12 @@ final class ElasticsearchPlugin extends AbstractPlugin implements PluginInterfac public function init() { $config = self::loadConfig(); + $hosts = $config->get("hosts"); + $rawGatewayFactory = new RawGatewayFactory(); + $rawGateway = $rawGatewayFactory->build($hosts); + if ($types = $config->get("types")) { - $hosts = $config->get("hosts"); $eventManager = Pimcore::getEventManager(); if ($assetConfig = $types->get("asset")) { diff --git a/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGateway.php b/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGateway.php new file mode 100644 index 0000000..faba613 --- /dev/null +++ b/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGateway.php @@ -0,0 +1,145 @@ + + */ +final class RawGateway extends AbstractGateway +{ + /** + * @var RawGateway + */ + private static $instance; + + /** + * @var Client + */ + private $client; + + /** + * @var ZendEventManager + */ + private $pimcoreEventManager; + + /** + * Constructor + * + * @param Client $client + * @param ZendEventManager $pimcoreEventManager + */ + public function __construct( + Client $client, + ZendEventManager $pimcoreEventManager + ) { + $this->client = $client; + $this->pimcoreEventManager = $pimcoreEventManager; + + static::$instance = $this; + } + + /** + * Get an instance of this gateway after plugin initialisation + * + * @return RawGateway + */ + public static function getInstance() + { + if (null === static::$instance) { + throw new \RuntimeException("No instance of RawGateway available, did the Elasticsearch plugin initialise correctly?"); + } + + return static::$instance; + } + + /** + * Save the given data + * + * @param array $data + * + * @return void + */ + public function save(array $data) + { + $this->client->index($data); + } + + /** + * {@inheritdoc} + */ + public function findBy( + array $query, + array $additionalOptions = [], + array $resultOptions = [] + ) { + throw new \Exception("Not implemented"); + } + + /** + * Perform a search on the given index and type. + * + * @param string $index + * @param string $type + * @param array $query + * + * @return ResultsList + */ + public function findByArray($index, $type, array $query) + { + return $this->doFind($index, $type, $query); + } + + /** + * Perform a search on the given index and type. + * + * @param string $index + * @param string $type + * @param QueryBuilder $query + * + * @return ResultsList + */ + public function findByQueryBuilder($index, $type, QueryBuilder $query) + { + return $this->doFind($index, $type, $query->toArray()); + } + + /** + * Perform a search on the given index and type. + * + * @param string $index + * @param string $type + * @param array $query + * + * @return ResultsList + */ + private function doFind($index, $type, array $query) + { + $result = $this->doSearch( + $this->client, + $index, + $type, + $query + ); + + return new ResultsList($result, $result["hits"]["total"]); + } + +} diff --git a/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGatewayFactory.php b/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGatewayFactory.php new file mode 100644 index 0000000..4b53a75 --- /dev/null +++ b/lib/Byng/Pimcore/Elasticsearch/Gateway/RawGatewayFactory.php @@ -0,0 +1,40 @@ + + */ +final class RawGatewayFactory +{ + /** + * Build the RawGateway + * + * @param Zend_Config $hosts + * + * @return PageGateway + */ + public function build(\Zend_Config $hosts) + { + $client = ClientBuilder::fromConfig([ + "hosts" => $hosts->toArray() + ]); + + return new RawGateway($client, \Pimcore::getEventManager()); + } +} diff --git a/lib/Byng/Pimcore/Elasticsearch/Query/QueryBuilder.php b/lib/Byng/Pimcore/Elasticsearch/Query/QueryBuilder.php index baf5b54..b44ec93 100644 --- a/lib/Byng/Pimcore/Elasticsearch/Query/QueryBuilder.php +++ b/lib/Byng/Pimcore/Elasticsearch/Query/QueryBuilder.php @@ -13,7 +13,10 @@ namespace Byng\Pimcore\Elasticsearch\Query; +use Byng\Pimcore\Elasticsearch\Query\QueryInterface; + /** + * * QueryBuilder defines the query to send to elasticsearch. * * @author Asim Liaquat @@ -157,4 +160,127 @@ public function setSort(Sort $sort) $this->sort = $sort; } + /** + * Converts the query builder into an array + * + * @return array + */ + public function toArray() + { + $body = []; + + if ($query = $this->getQuery()) { + $body = $this->processQuery($query); + } + + if ($filter = $this->getFilter()) { + $body = array_merge($body, $this->processQuery($filter)); + } + + if ($from = $this->getFrom()) { + $body["from"] = $from; + } + + if ($size = $this->getSize()) { + $body["size"] = $size; + } + + if ($sort = $this->getSort()) { + $body["sort"] = $this->processQuery($sort); + } + + return $body; + } + + /** + * Process a query into an array usable by Elasticsearch + * + * @param QueryInterface $query + * + * @return array + */ + protected function processQuery(QueryInterface $query) + { + switch ($query->getType()) { + + case "query": + $result["query"] = $this->processQuery($query->getBoolQuery()); + break; + + case "filter": + $result["filter"] = $this->processQuery($query->getQuery()); + break; + + case "bool": + $boolResult = []; + + foreach ($query->getMust() as $must) { + $boolResult["must"][] = $this->processQuery($must); + } + + foreach ($query->getShould() as $should) { + $boolResult["should"][] = $this->processQuery($should); + } + + foreach ($query->getMustNot() as $mustNot) { + $boolResult["must_not"][] = $this->processQuery($mustNot); + } + + $result = []; + $result["bool"] = $boolResult; + + break; + + case "match": + $result = []; + + if ($operator = $query->getOperator()) { + $result["match"][$query->getField()] = [ + "query" => $query->getQuery(), + "operator" => $operator + ]; + } else { + $result["match"][$query->getField()] = $query->getQuery(); + } + break; + + case "range": + $result = []; + $result["range"][$query->getField()] = $query->getRanges(); + break; + + case "sort": + $result = []; + foreach ($query->getCriteria() as $column => $order) { + $result[$column]["order"] = $order; + } + break; + + case "terms": + $result["terms"] = [ + $query->getField() => $query->getTerms() + ]; + break; + + case "constant_score": + $result["constant_score"] = $this->processQuery($query->getFilter()); + break; + + case "nested": + $result["nested"] = [ + "path" => $query->getPath(), + "query" => $this->processQuery($query->getQuery()) + ]; + break; + + default: + throw new \InvalidArgumentException(sprintf( + "Unknown query type '%s' given.", + $query->getType() + )); + } + + return $result; + } + }