vendor/handcraftedinthealps/elasticsearch-bundle/Service/Repository.php line 289

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the ONGR package.
  4.  *
  5.  * (c) NFQ Technologies UAB <info@nfq.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace ONGR\ElasticsearchBundle\Service;
  11. use ONGR\ElasticsearchBundle\Result\ArrayIterator;
  12. use ONGR\ElasticsearchBundle\Result\RawIterator;
  13. use ONGR\ElasticsearchDSL\Query\FullText\QueryStringQuery;
  14. use ONGR\ElasticsearchDSL\Query\Compound\BoolQuery;
  15. use ONGR\ElasticsearchDSL\Search;
  16. use ONGR\ElasticsearchDSL\Sort\FieldSort;
  17. use ONGR\ElasticsearchBundle\Result\DocumentIterator;
  18. /**
  19.  * Document repository class.
  20.  */
  21. class Repository
  22. {
  23.     /**
  24.      * @var Manager
  25.      */
  26.     private $manager;
  27.     /**
  28.      * @var string Fully qualified class name
  29.      */
  30.     private $className;
  31.     /**
  32.      * @var string Elasticsearch type name
  33.      */
  34.     private $type;
  35.     /**
  36.      * Constructor.
  37.      *
  38.      * @param Manager $manager
  39.      * @param string  $className
  40.      */
  41.     public function __construct($manager$className)
  42.     {
  43.         if (!is_string($className)) {
  44.             throw new \InvalidArgumentException('Class name must be a string.');
  45.         }
  46.         if (!class_exists($className)) {
  47.             throw new \InvalidArgumentException(
  48.                 sprintf('Cannot create repository for non-existing class "%s".'$className)
  49.             );
  50.         }
  51.         $this->manager $manager;
  52.         $this->className $className;
  53.         $this->type $this->resolveType($className);
  54.     }
  55.     /**
  56.      * Returns elasticsearch manager used in the repository.
  57.      *
  58.      * @return Manager
  59.      */
  60.     public function getManager()
  61.     {
  62.         return $this->manager;
  63.     }
  64.     /**
  65.      * @return array
  66.      */
  67.     public function getType()
  68.     {
  69.         return $this->type;
  70.     }
  71.     /**
  72.      * Returns a single document data by ID or null if document is not found.
  73.      *
  74.      * @param string $id      Document ID to find
  75.      * @param string $routing Custom routing for the document
  76.      *
  77.      * @return object
  78.      */
  79.     public function find($id$routing null)
  80.     {
  81.         return $this->manager->find($this->type$id$routing);
  82.     }
  83.     /**
  84.      * Returns documents by a set of ids
  85.      *
  86.      * @param array $ids
  87.      *
  88.      * @return DocumentIterator The objects.
  89.      */
  90.     public function findByIds(array $ids)
  91.     {
  92.         $args = [];
  93.         $manager $this->getManager();
  94.         $args['body']['docs'] = [];
  95.         $args['index'] = $manager->getIndexName();
  96.         $args['type'] = $this->getType();
  97.         foreach ($ids as $id) {
  98.             $args['body']['docs'][] = [
  99.                 '_id' => $id
  100.             ];
  101.         }
  102.         $mgetResponse $manager->getClient()->mget($args);
  103.         $return = [
  104.             'hits' => [
  105.                 'hits' => [],
  106.                 'total' => 0,
  107.             ]
  108.         ];
  109.         foreach ($mgetResponse['docs'] as $item) {
  110.             if ($item['found']) {
  111.                 $return['hits']['hits'][] = $item;
  112.             }
  113.         }
  114.         $return['hits']['total'] = count($return['hits']['hits']);
  115.         return new DocumentIterator($return$manager);
  116.     }
  117.     /**
  118.      * Finds documents by a set of criteria.
  119.      *
  120.      * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
  121.      * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
  122.      * @param int|null   $limit      Example: 5.
  123.      * @param int|null   $offset     Example: 30.
  124.      *
  125.      * @return array|DocumentIterator The objects.
  126.      */
  127.     public function findBy(
  128.         array $criteria,
  129.         array $orderBy = [],
  130.         $limit null,
  131.         $offset null
  132.     ) {
  133.         $search $this->createSearch();
  134.         if ($limit !== null) {
  135.             $search->setSize($limit);
  136.         }
  137.         if ($offset !== null) {
  138.             $search->setFrom($offset);
  139.         }
  140.         foreach ($criteria as $field => $value) {
  141.             if (preg_match('/^!(.+)$/'$field)) {
  142.                 $boolType BoolQuery::MUST_NOT;
  143.                 $field preg_replace('/^!/'''$field);
  144.             } else {
  145.                 $boolType BoolQuery::MUST;
  146.             }
  147.             $search->addQuery(
  148.                 new QueryStringQuery(is_array($value) ? implode(' OR '$value) : $value, ['default_field' => $field]),
  149.                 $boolType
  150.             );
  151.         }
  152.         foreach ($orderBy as $field => $direction) {
  153.             $search->addSort(new FieldSort($field$direction));
  154.         }
  155.         return $this->findDocuments($search);
  156.     }
  157.     /**
  158.      * Finds a single document by a set of criteria.
  159.      *
  160.      * @param array      $criteria   Example: ['group' => ['best', 'worst'], 'job' => 'medic'].
  161.      * @param array|null $orderBy    Example: ['name' => 'ASC', 'surname' => 'DESC'].
  162.      *
  163.      * @return object|null The object.
  164.      */
  165.     public function findOneBy(array $criteria, array $orderBy = [])
  166.     {
  167.         return $this->findBy($criteria$orderBy1null)->current();
  168.     }
  169.     /**
  170.      * Returns search instance.
  171.      *
  172.      * @return Search
  173.      */
  174.     public function createSearch()
  175.     {
  176.         return new Search();
  177.     }
  178.     /**
  179.      * Parses scroll configuration from raw response.
  180.      *
  181.      * @param array  $raw
  182.      * @param string $scrollDuration
  183.      *
  184.      * @return array
  185.      */
  186.     public function getScrollConfiguration($raw$scrollDuration)
  187.     {
  188.         $scrollConfig = [];
  189.         if (isset($raw['_scroll_id'])) {
  190.             $scrollConfig['_scroll_id'] = $raw['_scroll_id'];
  191.             $scrollConfig['duration'] = $scrollDuration;
  192.         }
  193.         return $scrollConfig;
  194.     }
  195.     /**
  196.      * Returns DocumentIterator with composed Document objects from array response.
  197.      *
  198.      * @param Search $search
  199.      *
  200.      * @return DocumentIterator
  201.      */
  202.     public function findDocuments(Search $search)
  203.     {
  204.         $results $this->executeSearch($search);
  205.         return new DocumentIterator(
  206.             $results,
  207.             $this->getManager(),
  208.             $this->getScrollConfiguration($results$search->getScroll())
  209.         );
  210.     }
  211.     /**
  212.      * Returns ArrayIterator with access to unmodified documents directly.
  213.      *
  214.      * @param Search $search
  215.      *
  216.      * @return ArrayIterator
  217.      */
  218.     public function findArray(Search $search)
  219.     {
  220.         $results $this->executeSearch($search);
  221.         return new ArrayIterator(
  222.             $results,
  223.             $this->getManager(),
  224.             $this->getScrollConfiguration($results$search->getScroll())
  225.         );
  226.     }
  227.     /**
  228.      * Returns RawIterator with access to node with all returned values included.
  229.      *
  230.      * @param Search $search
  231.      *
  232.      * @return RawIterator
  233.      */
  234.     public function findRaw(Search $search)
  235.     {
  236.         $results $this->executeSearch($search);
  237.         return new RawIterator(
  238.             $results,
  239.             $this->getManager(),
  240.             $this->getScrollConfiguration($results$search->getScroll())
  241.         );
  242.     }
  243.     /**
  244.      * Executes search to the elasticsearch and returns raw response.
  245.      *
  246.      * @param Search $search
  247.      *
  248.      * @return array
  249.      */
  250.     private function executeSearch(Search $search)
  251.     {
  252.         return $this->getManager()->search([$this->getType()], $search->toArray(), $search->getUriParams());
  253.     }
  254.     /**
  255.      * Counts documents by given search.
  256.      *
  257.      * @param Search $search
  258.      * @param array  $params
  259.      * @param bool   $returnRaw If set true returns raw response gotten from client.
  260.      *
  261.      * @return int|array
  262.      */
  263.     public function count(Search $search, array $params = [], $returnRaw false)
  264.     {
  265.         $body array_merge(
  266.             [
  267.                 'index' => $this->getManager()->getIndexName(),
  268.                 'type' => $this->type,
  269.                 'body' => $search->toArray(),
  270.             ],
  271.             $params
  272.         );
  273.         $results $this
  274.             ->getManager()
  275.             ->getClient()->count($body);
  276.         if ($returnRaw) {
  277.             return $results;
  278.         } else {
  279.             return $results['count'];
  280.         }
  281.     }
  282.     /**
  283.      * Removes a single document data by ID.
  284.      *
  285.      * @param string $id      Document ID to remove
  286.      * @param string $routing Custom routing for the document
  287.      *
  288.      * @return array
  289.      *
  290.      * @throws \LogicException
  291.      */
  292.     public function remove($id$routing null)
  293.     {
  294.         $params = [
  295.             'index' => $this->getManager()->getIndexName(),
  296.             'type' => $this->type,
  297.             'id' => $id,
  298.         ];
  299.         if ($routing) {
  300.             $params['routing'] = $routing;
  301.         }
  302.         $response $this->getManager()->getClient()->delete($params);
  303.         return $response;
  304.     }
  305.     /**
  306.      * Partial document update.
  307.      *
  308.      * @param string $id     Document id to update.
  309.      * @param array  $fields Fields array to update.
  310.      * @param string $script Groovy script to update fields.
  311.      * @param array  $params Additional parameters to pass to the client.
  312.      *
  313.      * @return array
  314.      */
  315.     public function update($id, array $fields = [], $script null, array $params = [])
  316.     {
  317.         $body array_filter(
  318.             [
  319.                 'doc' => $fields,
  320.                 'script' => $script,
  321.             ]
  322.         );
  323.         $params array_merge(
  324.             [
  325.                 'id' => $id,
  326.                 'index' => $this->getManager()->getIndexName(),
  327.                 'type' => $this->type,
  328.                 'body' => $body,
  329.             ],
  330.             $params
  331.         );
  332.         return $this->getManager()->getClient()->update($params);
  333.     }
  334.     /**
  335.      * Resolves elasticsearch type by class name.
  336.      *
  337.      * @param string $className
  338.      *
  339.      * @return array
  340.      */
  341.     private function resolveType($className)
  342.     {
  343.         return $this->getManager()->getMetadataCollector()->getDocumentType($className);
  344.     }
  345.     /**
  346.      * Returns fully qualified class name.
  347.      *
  348.      * @return string
  349.      */
  350.     public function getClassName()
  351.     {
  352.         return $this->className;
  353.     }
  354. }