vendor/ruflin/elastica/lib/Elastica/Type.php line 352

Open in your IDE?
  1. <?php
  2. namespace Elastica;
  3. use Elastica\Exception\InvalidException;
  4. use Elastica\Exception\NotFoundException;
  5. use Elastica\Exception\RuntimeException;
  6. use Elastica\ResultSet\BuilderInterface;
  7. use Elastica\Script\AbstractScript;
  8. use Elastica\Type\Mapping;
  9. use Elasticsearch\Endpoints\AbstractEndpoint;
  10. use Elasticsearch\Endpoints\Delete;
  11. use Elasticsearch\Endpoints\DeleteByQuery;
  12. use Elasticsearch\Endpoints\Indices\Mapping\Get;
  13. use Elasticsearch\Endpoints\Indices\Type\Exists;
  14. /**
  15.  * Elastica type object.
  16.  *
  17.  * elasticsearch has for every types as a substructure. This object
  18.  * represents a type inside a context
  19.  * The hierarchy is as following: client -> index -> type -> document
  20.  *
  21.  * @author   Nicolas Ruflin <spam@ruflin.com>
  22.  */
  23. class Type implements SearchableInterface
  24. {
  25.     /**
  26.      * Index.
  27.      *
  28.      * @var \Elastica\Index Index object
  29.      */
  30.     protected $_index;
  31.     /**
  32.      * Type name.
  33.      *
  34.      * @var string Type name
  35.      */
  36.     protected $_name;
  37.     /**
  38.      * @var array|string A callable that serializes an object passed to it
  39.      */
  40.     protected $_serializer;
  41.     /**
  42.      * Creates a new type object inside the given index.
  43.      *
  44.      * @param \Elastica\Index $index Index Object
  45.      * @param string          $name  Type name
  46.      */
  47.     public function __construct(Index $index$name)
  48.     {
  49.         $this->_index $index;
  50.         $this->_name $name;
  51.     }
  52.     /**
  53.      * Adds the given document to the search index.
  54.      *
  55.      * @param \Elastica\Document $doc Document with data
  56.      *
  57.      * @return \Elastica\Response
  58.      */
  59.     public function addDocument(Document $doc)
  60.     {
  61.         $endpoint = new \Elasticsearch\Endpoints\Index();
  62.         if (null !== $doc->getId() && '' !== $doc->getId()) {
  63.             $endpoint->setID($doc->getId());
  64.         }
  65.         $options $doc->getOptions(
  66.             [
  67.                 'version',
  68.                 'version_type',
  69.                 'routing',
  70.                 'percolate',
  71.                 'parent',
  72.                 'op_type',
  73.                 'consistency',
  74.                 'replication',
  75.                 'refresh',
  76.                 'timeout',
  77.             ]
  78.         );
  79.         $endpoint->setBody($doc->getData());
  80.         $endpoint->setParams($options);
  81.         $response $this->requestEndpoint($endpoint);
  82.         $data $response->getData();
  83.         // set autogenerated id to document
  84.         if (($doc->isAutoPopulate()
  85.                 || $this->getIndex()->getClient()->getConfigValue(['document''autoPopulate'], false))
  86.             && $response->isOk()
  87.         ) {
  88.             if (!$doc->hasId()) {
  89.                 if (isset($data['_id'])) {
  90.                     $doc->setId($data['_id']);
  91.                 }
  92.             }
  93.             if (isset($data['_version'])) {
  94.                 $doc->setVersion($data['_version']);
  95.             }
  96.         }
  97.         return $response;
  98.     }
  99.     /**
  100.      * @param $object
  101.      * @param Document $doc
  102.      *
  103.      * @throws Exception\RuntimeException
  104.      *
  105.      * @return Response
  106.      */
  107.     public function addObject($objectDocument $doc null)
  108.     {
  109.         if (!isset($this->_serializer)) {
  110.             throw new RuntimeException('No serializer defined');
  111.         }
  112.         $data call_user_func($this->_serializer$object);
  113.         if (!$doc) {
  114.             $doc = new Document();
  115.         }
  116.         $doc->setData($data);
  117.         return $this->addDocument($doc);
  118.     }
  119.     /**
  120.      * Update document, using update script. Requires elasticsearch >= 0.19.0.
  121.      *
  122.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update.html
  123.      *
  124.      * @param \Elastica\Document|\Elastica\Script\AbstractScript $data    Document with update data
  125.      * @param array                                              $options array of query params to use for query. For possible options check es api
  126.      *
  127.      * @throws \Elastica\Exception\InvalidException
  128.      *
  129.      * @return \Elastica\Response
  130.      */
  131.     public function updateDocument($data, array $options = [])
  132.     {
  133.         if (!($data instanceof Document) && !($data instanceof AbstractScript)) {
  134.             throw new \InvalidArgumentException('Data should be a Document or Script');
  135.         }
  136.         if (!$data->hasId()) {
  137.             throw new InvalidException('Document or Script id is not set');
  138.         }
  139.         return $this->getIndex()->getClient()->updateDocument(
  140.             $data->getId(),
  141.             $data,
  142.             $this->getIndex()->getName(),
  143.             $this->getName(),
  144.             $options
  145.         );
  146.     }
  147.     /**
  148.      * Uses _bulk to send documents to the server.
  149.      *
  150.      * @param array|\Elastica\Document[] $docs Array of Elastica\Document
  151.      *
  152.      * @return \Elastica\Bulk\ResponseSet
  153.      *
  154.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  155.      */
  156.     public function updateDocuments(array $docs)
  157.     {
  158.         foreach ($docs as $doc) {
  159.             $doc->setType($this->getName());
  160.         }
  161.         return $this->getIndex()->updateDocuments($docs);
  162.     }
  163.     /**
  164.      * Uses _bulk to send documents to the server.
  165.      *
  166.      * @param array|\Elastica\Document[] $docs Array of Elastica\Document
  167.      *
  168.      * @return \Elastica\Bulk\ResponseSet
  169.      *
  170.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  171.      */
  172.     public function addDocuments(array $docs)
  173.     {
  174.         foreach ($docs as $doc) {
  175.             $doc->setType($this->getName());
  176.         }
  177.         return $this->getIndex()->addDocuments($docs);
  178.     }
  179.     /**
  180.      * Uses _bulk to send documents to the server.
  181.      *
  182.      * @param objects[] $objects
  183.      *
  184.      * @return \Elastica\Bulk\ResponseSet
  185.      *
  186.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  187.      */
  188.     public function addObjects(array $objects)
  189.     {
  190.         if (!isset($this->_serializer)) {
  191.             throw new RuntimeException('No serializer defined');
  192.         }
  193.         $docs = [];
  194.         foreach ($objects as $object) {
  195.             $data call_user_func($this->_serializer$object);
  196.             $doc = new Document();
  197.             $doc->setData($data);
  198.             $doc->setType($this->getName());
  199.             $docs[] = $doc;
  200.         }
  201.         return $this->getIndex()->addDocuments($docs);
  202.     }
  203.     /**
  204.      * Get the document from search index.
  205.      *
  206.      * @param string $id      Document id
  207.      * @param array  $options Options for the get request.
  208.      *
  209.      * @throws \Elastica\Exception\NotFoundException
  210.      * @throws \Elastica\Exception\ResponseException
  211.      *
  212.      * @return \Elastica\Document
  213.      */
  214.     public function getDocument($id$options = [])
  215.     {
  216.         $endpoint = new \Elasticsearch\Endpoints\Get();
  217.         $endpoint->setID($id);
  218.         $endpoint->setParams($options);
  219.         $response $this->requestEndpoint($endpoint);
  220.         $result $response->getData();
  221.         if (!isset($result['found']) || $result['found'] === false) {
  222.             throw new NotFoundException('doc id '.$id.' not found');
  223.         }
  224.         if (isset($result['fields'])) {
  225.             $data $result['fields'];
  226.         } elseif (isset($result['_source'])) {
  227.             $data $result['_source'];
  228.         } else {
  229.             $data = [];
  230.         }
  231.         $document = new Document($id$data$this->getName(), $this->getIndex());
  232.         $document->setVersion($result['_version']);
  233.         return $document;
  234.     }
  235.     /**
  236.      * @param string       $id
  237.      * @param array|string $data
  238.      *
  239.      * @return Document
  240.      */
  241.     public function createDocument($id ''$data = [])
  242.     {
  243.         $document = new Document($id$data);
  244.         $document->setType($this);
  245.         return $document;
  246.     }
  247.     /**
  248.      * Returns the type name.
  249.      *
  250.      * @return string Type name
  251.      */
  252.     public function getName()
  253.     {
  254.         return $this->_name;
  255.     }
  256.     /**
  257.      * Sets value type mapping for this type.
  258.      *
  259.      * @param \Elastica\Type\Mapping|array $mapping Elastica\Type\MappingType object or property array with all mappings
  260.      * @param array                        $query   querystring when put mapping (for example update_all_types)
  261.      *
  262.      * @return \Elastica\Response
  263.      */
  264.     public function setMapping($mapping, array $query = [])
  265.     {
  266.         $mapping Mapping::create($mapping);
  267.         $mapping->setType($this);
  268.         return $mapping->send($query);
  269.     }
  270.     /**
  271.      * Returns current mapping for the given type.
  272.      *
  273.      * @return array Current mapping
  274.      */
  275.     public function getMapping()
  276.     {
  277.         $response $this->requestEndpoint(new Get());
  278.         $data $response->getData();
  279.         $mapping array_shift($data);
  280.         if (isset($mapping['mappings'])) {
  281.             return $mapping['mappings'];
  282.         }
  283.         return [];
  284.     }
  285.     /**
  286.      * Create search object.
  287.      *
  288.      * @param string|array|\Elastica\Query $query   Array with all query data inside or a Elastica\Query object
  289.      * @param int|array                    $options OPTIONAL Limit or associative array of options (option=>value)
  290.      * @param BuilderInterface             $builder
  291.      *
  292.      * @return Search
  293.      */
  294.     public function createSearch($query ''$options nullBuilderInterface $builder null)
  295.     {
  296.         $search $this->getIndex()->createSearch($query$options$builder);
  297.         $search->addType($this);
  298.         return $search;
  299.     }
  300.     /**
  301.      * Do a search on this type.
  302.      *
  303.      * @param string|array|\Elastica\Query $query   Array with all query data inside or a Elastica\Query object
  304.      * @param int|array                    $options OPTIONAL Limit or associative array of options (option=>value)
  305.      *
  306.      * @return \Elastica\ResultSet with all results inside
  307.      *
  308.      * @see \Elastica\SearchableInterface::search
  309.      */
  310.     public function search($query ''$options null)
  311.     {
  312.         $search $this->createSearch($query$options);
  313.         return $search->search();
  314.     }
  315.     /**
  316.      * Count docs by query.
  317.      *
  318.      * @param string|array|\Elastica\Query $query Array with all query data inside or a Elastica\Query object
  319.      *
  320.      * @return int number of documents matching the query
  321.      *
  322.      * @see \Elastica\SearchableInterface::count
  323.      */
  324.     public function count($query '')
  325.     {
  326.         $search $this->createSearch($query);
  327.         return $search->count();
  328.     }
  329.     /**
  330.      * Returns index client.
  331.      *
  332.      * @return \Elastica\Index Index object
  333.      */
  334.     public function getIndex()
  335.     {
  336.         return $this->_index;
  337.     }
  338.     /**
  339.      * @param \Elastica\Document $document
  340.      *
  341.      * @return \Elastica\Response
  342.      */
  343.     public function deleteDocument(Document $document)
  344.     {
  345.         $options $document->getOptions(
  346.             [
  347.                 'version',
  348.                 'version_type',
  349.                 'routing',
  350.                 'parent',
  351.                 'replication',
  352.                 'consistency',
  353.                 'refresh',
  354.                 'timeout',
  355.             ]
  356.         );
  357.         return $this->deleteById($document->getId(), $options);
  358.     }
  359.     /**
  360.      * Uses _bulk to delete documents from the server.
  361.      *
  362.      * @param array|\Elastica\Document[] $docs Array of Elastica\Document
  363.      *
  364.      * @return \Elastica\Bulk\ResponseSet
  365.      *
  366.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
  367.      */
  368.     public function deleteDocuments(array $docs)
  369.     {
  370.         foreach ($docs as $doc) {
  371.             $doc->setType($this->getName());
  372.         }
  373.         return $this->getIndex()->deleteDocuments($docs);
  374.     }
  375.     /**
  376.      * Deletes an entry by its unique identifier.
  377.      *
  378.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete.html
  379.      *
  380.      * @param int|string $id      Document id
  381.      * @param array      $options
  382.      *
  383.      * @throws \InvalidArgumentException
  384.      * @throws \Elastica\Exception\NotFoundException
  385.      *
  386.      * @return \Elastica\Response Response object
  387.      */
  388.     public function deleteById($id, array $options = [])
  389.     {
  390.         if (empty($id) || !trim($id)) {
  391.             throw new \InvalidArgumentException();
  392.         }
  393.         $endpoint = new Delete();
  394.         $endpoint->setID($id);
  395.         $endpoint->setParams($options);
  396.         $response $this->requestEndpoint($endpoint);
  397.         $responseData $response->getData();
  398.         if (isset($responseData['found']) && false == $responseData['found']) {
  399.             throw new NotFoundException('Doc id '.$id.' not found and can not be deleted');
  400.         }
  401.         return $response;
  402.     }
  403.     /**
  404.      * Deletes the given list of ids from this type.
  405.      *
  406.      * @param array       $ids
  407.      * @param string|bool $routing Optional routing key for all ids
  408.      *
  409.      * @return \Elastica\Response Response  object
  410.      */
  411.     public function deleteIds(array $ids$routing false)
  412.     {
  413.         return $this->getIndex()->getClient()->deleteIds($ids$this->getIndex(), $this$routing);
  414.     }
  415.     /**
  416.      * Deletes entries in the db based on a query.
  417.      *
  418.      * @param \Elastica\Query|\Elastica\Query\AbstractQuery|string|array $query   Query object
  419.      * @param array                                                      $options Optional params
  420.      *
  421.      * @return \Elastica\Response
  422.      *
  423.      * @link https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
  424.      */
  425.     public function deleteByQuery($query, array $options = [])
  426.     {
  427.         $query Query::create($query);
  428.         $endpoint = new DeleteByQuery();
  429.         $endpoint->setBody($query->toArray());
  430.         $endpoint->setParams($options);
  431.         return $this->requestEndpoint($endpoint);
  432.     }
  433.     /**
  434.      * Makes calls to the elasticsearch server based on this type.
  435.      *
  436.      * @param string $path   Path to call
  437.      * @param string $method Rest method to use (GET, POST, DELETE, PUT)
  438.      * @param array  $data   OPTIONAL Arguments as array
  439.      * @param array  $query  OPTIONAL Query params
  440.      *
  441.      * @return \Elastica\Response Response object
  442.      */
  443.     public function request($path$method$data = [], array $query = [])
  444.     {
  445.         $path $this->getName().'/'.$path;
  446.         return $this->getIndex()->request($path$method$data$query);
  447.     }
  448.     /**
  449.      * Makes calls to the elasticsearch server with usage official client Endpoint based on this type.
  450.      *
  451.      * @param AbstractEndpoint $endpoint
  452.      *
  453.      * @return Response
  454.      */
  455.     public function requestEndpoint(AbstractEndpoint $endpoint)
  456.     {
  457.         $cloned = clone $endpoint;
  458.         $cloned->setType($this->getName());
  459.         return $this->getIndex()->requestEndpoint($cloned);
  460.     }
  461.     /**
  462.      * Sets the serializer callable used in addObject.
  463.      *
  464.      * @see \Elastica\Type::addObject
  465.      *
  466.      * @param array|string $serializer @see \Elastica\Type::_serializer
  467.      *
  468.      * @return $this
  469.      */
  470.     public function setSerializer($serializer)
  471.     {
  472.         $this->_serializer $serializer;
  473.         return $this;
  474.     }
  475.     /**
  476.      * Checks if the given type exists in Index.
  477.      *
  478.      * @return bool True if type exists
  479.      */
  480.     public function exists()
  481.     {
  482.         $response $this->requestEndpoint(new Exists());
  483.         return $response->getStatus() === 200;
  484.     }
  485. }