/** * @param string $search * @return ResultSet */ public function search($search) { $query = new Query(); $query->setQuery($this->getBoolQuery($search)); $query = $this->searchManager->createQuery()->searchWith($query)->hydrateWith($this->getHydrateQuery())->setMaxResults(50); $this->onSearch($search, $query); return $query->getResult(); }
protected function execute(InputInterface $input, OutputInterface $output) { $printMapping = $output->getVerbosity() > $output::VERBOSITY_NORMAL; $metadataFactory = $this->searchManager->getMetadataFactory(); /** @var ClassMetadata $class */ foreach ($metadataFactory->getAllMetadata() as $class) { $output->writeln(sprintf('Entity <info>%s</info> is searchable', $class->getName())); if (!$printMapping) { continue; } $meta = (array) $class; unset($meta['reflFields'], $meta['reflClass']); $output->writeln(Dumper::toTerminal($meta)); } }
/** * Execute search and hydrate results if required. * * @param integer $hydrationMode * @throws DoctrineSearchException * @return mixed */ public function getResult($hydrationMode = null) { if ($hydrationMode) { $this->hydrationMode = $hydrationMode; } $classes = array(); foreach ($this->entityClasses as $entityClass) { $classes[] = $this->sm->getClassMetadata($entityClass); } $resultSet = $this->getSearchManager()->getClient()->search($this->query, $classes); // TODO: abstraction of support for different result sets if ($resultSet instanceof Elastica\ResultSet) { $this->count = $resultSet->getTotalHits(); $this->facets = $resultSet->getFacets(); $results = $resultSet->getResults(); } else { $resultClass = get_class($resultSet); throw new DoctrineSearchException("Unexpected result set class '{$resultClass}'"); } // Return results depending on hydration mode if ($this->hydrationMode == self::HYDRATE_BYPASS) { return $resultSet; } elseif ($this->hydrationMode == self::HYDRATE_INTERNAL) { return $this->sm->getUnitOfWork()->hydrateCollection($classes, $resultSet); } // Document ids are used to lookup dbms results $fn = function ($result) { return $result->getId(); }; $ids = array_map($fn, $results); return $this->getHydrationQuery()->setParameter($this->hydrationParameter, $ids ?: null)->useResultCache($this->useResultCache, $this->cacheLifetime)->getResult($this->hydrationMode); }
/** * Construct an entity object * * @param ClassMetadata $class * @param object $document */ public function hydrateEntity(ClassMetadata $class, $document) { // TODO: add support for different result set types from different clients // perhaps by wrapping documents in a layer of abstraction $data = $document->getData(); $fields = array_merge($document->hasFields() ? $document->getFields() : array(), array('_version' => $document->getVersion())); foreach ($fields as $name => $value) { if (isset($class->parameters[$name])) { $data[$name] = $value; } else { foreach ($class->parameters as $param => $mapping) { if ($mapping->name == $name) { $data[$param] = $value; break; } } } } $data[$class->getIdentifier()] = $document->getId(); if (method_exists($document, 'getScore')) { $data['score'] = $document->getScore(); } $entity = $this->sm->getSerializer()->deserialize($class->className, json_encode($data)); if ($this->evm->hasListeners(Events::postLoad)) { $this->evm->dispatchEvent(Events::postLoad, new Event\LifecycleEventArgs($entity, $this->sm)); } return $entity; }
/** * Execute a direct delete by query on the associated index and type * * @param object $query */ public function delete($query) { $classes = $this->getClassMetadata(); foreach ($classes as $class) { $this->_sm->getClient()->removeAll($class, $query); } }
/** * @param BaseElasticsearchEntity $entity * @param bool $refresh * * @throws \Exception */ public function save($entity, $refresh = false) { $this->_sm->persist($entity); $this->_sm->flush($entity); if ($refresh) { $this->_sm->getClient()->refreshIndex($this->getClassMetadata()->getIndexForWrite($entity->toESDocument())); } }
public function indexEntities(ClassMetadata $searchMeta) { foreach ($this->searchManager->getMetadataFactory()->getAllMetadata() as $otherMeta) { if ($searchMeta->className === $otherMeta->className) { continue; } if (is_subclass_of($searchMeta->className, $otherMeta->className)) { $this->onChildSkipped($this, $searchMeta, $otherMeta); return; } } if ($searchMeta->riverImplementation) { $river = $this->serviceLocator->getByType($searchMeta->riverImplementation); } else { /** @var River\DefaultEntityRiver $river */ $river = $this->serviceLocator->createInstance('Kdyby\\DoctrineSearch\\River\\DefaultEntityRiver'); } if (!$river instanceof EntityRiver) { throw new UnexpectedValueException('The river must implement Doctrine\\Search\\EntityRiver.'); } if (property_exists($river, 'onIndexStart')) { $river->onIndexStart[] = function (EntityRiver $river, $paginator, ORMMetadata $class) { $this->onIndexStart($this, $paginator, $river, $class); }; } if (property_exists($river, 'onItemsIndexed')) { $river->onItemsIndexed[] = function ($self, $entities) { $this->onItemsIndexed($this, $entities); }; } if (property_exists($river, 'onIndexStats')) { $river->onIndexStats[] = function ($self, ORMMetadata $class, $timeToIndex, $timeToRead) { $this->onIndexStats($this, $class, $timeToIndex, $timeToRead); }; } // disable logger $config = $this->entityManager->getConfiguration(); $oldLogger = $config->getSQLLogger(); $config->setSQLLogger(NULL); $river->transfuse($searchMeta); $config->setSQLLogger($oldLogger); }
protected function execute(InputInterface $input, OutputInterface $output) { $metadataFactory = $this->searchManager->getClassMetadataFactory(); $classes = $metadataFactory->getAllMetadata(); if ($input->getOption('drop-before')) { $this->schema->dropMappings($classes); } $aliases = $this->schema->createMappings($classes, TRUE); if ($input->getOption('init-data')) { $indexAliases = array(); foreach ($aliases as $alias => $original) { $indexAliases[] = $alias . '=' . $original; } $exitCode = $this->getApplication()->doRun(new ArrayInput(array('elastica:pipe-entities', 'index-aliases' => $indexAliases)), $output); if ($exitCode !== 0) { return 1; } } $output->writeln(''); $this->schema->createAliases($aliases); return 0; }
/** * (non-PHPdoc) * * @see \Zend\ServiceManager\FactoryInterface::createService() * * @return \Doctrine\Search\SearchManager */ public function createService(ServiceLocatorInterface $serviceLocator) { $this->setServiceLocator($serviceLocator); $config = $serviceLocator->get('Config'); $clientConfig = isset($config['elastica']['clients']) ? $config['elastica']['clients'] : []; $entityConfig = isset($config['elastica']['entities']) ? $config['elastica']['entities'] : ['paths' => []]; $indicesConfig = isset($config['elastica']['indices']) ? $config['elastica']['indices'] : []; $serializationGroups = isset($config['elastica']['serialization']['groups']) ? $config['elastica']['serialization']['groups'] : []; $searchConfig = new Configuration(); $md = $searchConfig->newDefaultAnnotationDriver($entityConfig['paths']); $searchConfig->setMetadataDriverImpl($md); $searchConfig->setMetadataCacheImpl(new ArrayCache()); $serializationContext = SerializationContext::create(); $serializationContext->enableMaxDepthChecks()->setGroups($serializationGroups); $searchConfig->setEntitySerializer(new JMSSerializer($serializationContext)); $eventManager = new EventManager(); $searchManager = new SearchManager($searchConfig, new ElasticSearchClient(new ElasticaClient(['connections' => $clientConfig])), $eventManager); try { $client = $searchManager->getClient(); $metadatas = $searchManager->getMetadataFactory()->getAllMetadata(); // Create indexes and types foreach ($metadatas as $metadata) { $config = isset($indicesConfig[$metadata->index]['settings']) ? $indicesConfig[$metadata->index]['settings'] : []; if (!$client->getIndex($metadata->index)->exists()) { $client->createIndex($metadata->index, $config); } $client->createType($metadata); } } catch (\Exception $e) { $this->getFlashMessenger()->addErrorMessage($e->getMessage()); /* @var $logger \Zend\Log\Logger */ $logger = $serviceLocator->get('logger'); $logger->debug($e->getMessage()); } return $searchManager; }
/** * Delete all indices */ public function deleteAllIndices() { /** @var ClassMetadata[] $metadatas */ $metadatas = $this->sm->getMetadataFactory()->getAllMetadata(); foreach ($metadatas as $metadata) { try { $this->client->deleteIndex($metadata->getIndexForRead()); } catch (ResponseException $e) { if (strpos($e->getResponse()->getError(), 'IndexMissingException') === false) { // The original error from ES is not "IndexMissingException". We shouldn't swallow it. throw $e; } // The index has been deleted already, skip it. } } }
protected function execute(InputInterface $input, OutputInterface $output) { $metaFactory = $this->searchManager->getClassMetadataFactory(); /** @var \Doctrine\Search\Mapping\ClassMetadata[] $classes */ $allClassesForIndex = $metaFactory->getAllMetadata(); if ($onlyEntity = $input->getOption('entity')) { $classes = [$metaFactory->getMetadataFor($onlyEntity)]; } else { $classes = $metaFactory->getAllMetadata(); } /** @var ProgressBar $progress */ $progress = NULL; $this->entityPiper->onIndexStart[] = function ($ep, Nette\Utils\Paginator $paginator, EntityRiver $river, ORMMetadata $class) use($output, &$progress) { $output->writeln(sprintf('Indexing <info>%s</info> using <info>%s</info>', $class->getName(), get_class($river))); if ($paginator->getItemCount() <= 0) { $output->writeln(" 0/0 River didn't return any results"); return; } $progress = new ProgressBar($output, $paginator->getItemCount()); $progress->setFormat($progress::getFormatDefinition('debug')); $progress->start(); }; $this->entityPiper->onIndexStats[] = function ($ep, ORMMetadata $meta, $timeToIndex, $timeToRead) use($input, $output) { if (!$input->getOption('stats')) { return; } $format = function ($time) { if ($time < 10) { return number_format($time * 1000, 6, '.', '') . ' ms'; } else { return number_format($time, 2, '.', '') . ' s'; } }; $output->writeln(sprintf(" ... Loading data took %s, indexing took %s", $format($timeToRead), $format($timeToIndex))); }; $this->entityPiper->onItemsIndexed[] = function ($ep, $entities) use($output, &$progress) { $progress->advance(count($entities)); }; $this->entityPiper->onChildSkipped[] = function ($ep, ClassMetadata $meta, ClassMetadata $parent) use($output, &$progress) { $output->writeln(sprintf('<info>%s</info> is a subclass of <info>%s</info> (being piped into <info>%s</info> type), ignoring.', $meta->className, $parent->className, $parent->type->name)); $progress = NULL; }; $aliases = array(); $indexAliases = $input->getArgument('index-aliases'); foreach ($indexAliases as $tmp) { list($alias, $original) = explode('=', $tmp, 2); $aliases[$original] = $alias; } foreach ($allClassesForIndex as $class) { //subclass bug if (isset($aliases[$class->getIndexName()])) { $class->index->name = $aliases[$class->getIndexName()]; } } foreach ($classes as $class) { $output->writeln(''); if ($old = array_search($class->getIndexName(), $aliases, TRUE)) { $output->writeln(sprintf('Redirecting data from <info>%s</info> to <info>%s</info>', $old, $class->getIndexName())); } unset($e); try { $this->entityPiper->indexEntities($class); } catch (\Exception $e) { } if (isset($e)) { // fix the metadata if ($old = array_search($class->getIndexName(), $aliases, TRUE)) { $class->index->name = $old; } throw $e; } if ($progress !== NULL) { $progress->finish(); } $output->writeln(''); } foreach ($allClassesForIndex as $class) { //subclass bug // fix the metadata if ($old = array_search($class->getIndexName(), $aliases, TRUE)) { $class->index->name = $old; } } }
/** * Execute a direct delete by query on the associated index and type * * @param object $query */ public function delete($query) { $this->_sm->getClient()->removeAll($this->_class, $query); }
public function testGetClassMetadataFactory() { $mdf = $this->sm->getClassMetadataFactory(); $this->assertInstanceOf('Doctrine\\Search\\Mapping\\ClassMetadataFactory', $mdf); }
/** * {@inheritDoc} */ protected function initialize() { $this->driver = $this->config->getMetadataDriverImpl(); $this->evm = $this->sm->getEventManager(); $this->initialized = true; }
protected function doRemoveEntities($entities) { $this->searchManager->remove($entities); }