/** * Builds a Mapping collection from the annotation sources that are present * * @throws \Flowpack\ElasticSearch\Exception * @return \Flowpack\ElasticSearch\Mapping\MappingCollection<\Flowpack\ElasticSearch\Domain\Model\Mapping> */ public function buildMappingInformation() { if (!$this->client instanceof Model\Client) { throw new \Flowpack\ElasticSearch\Exception('No client was given for mapping retrieval. Set a client BackendMappingBuilder->setClient().', 1339678111); } $this->indicesWithoutTypeInformation = array(); $response = $this->client->request('GET', '/_mapping'); $mappingInformation = new MappingCollection(MappingCollection::TYPE_BACKEND); $mappingInformation->setClient($this->client); $indexNames = $this->indexInformer->getAllIndexNames(); foreach ($response->getTreatedContent() as $indexName => $indexSettings) { if (!in_array($indexName, $indexNames)) { continue; } $index = new Model\Index($indexName); if (empty($indexSettings)) { $this->indicesWithoutTypeInformation[] = $indexName; } foreach ($indexSettings as $typeName => $typeSettings) { $type = new Model\GenericType($index, $typeName); $mapping = new Model\Mapping($type); if (isset($typeSettings['properties'])) { foreach ($typeSettings['properties'] as $propertyName => $propertySettings) { foreach ($propertySettings as $key => $value) { $mapping->setPropertyByPath(array($propertyName, $key), $value); } } } $mappingInformation->add($mapping); } } return $mappingInformation; }
/** * @param string $className * @param \Flowpack\ElasticSearch\Annotations\Indexable $annotation * @return Mapping */ protected function buildMappingFromClassAndAnnotation($className, \Flowpack\ElasticSearch\Annotations\Indexable $annotation) { $index = new \Flowpack\ElasticSearch\Domain\Model\Index($annotation->indexName); $type = new \Flowpack\ElasticSearch\Domain\Model\GenericType($index, $annotation->typeName); $mapping = new Mapping($type); foreach ($this->indexInformer->getClassProperties($className) as $propertyName) { $this->augmentMappingByProperty($mapping, $className, $propertyName); } return $mapping; }
/** * Returns the ElasticSearch type for a specific object, by its annotation * * @param $object * @param \Flowpack\ElasticSearch\Domain\Model\Client $client * * @return \Flowpack\ElasticSearch\Domain\Model\GenericType */ protected function getIndexTypeForObject($object, Client $client = null) { if ($client === null) { $client = $this->client; } $className = $this->reflectionService->getClassNameByObject($object); $indexAnnotation = $this->indexInformer->getClassAnnotation($className); if ($indexAnnotation === null) { return null; } $index = $client->findIndex($indexAnnotation->indexName); $type = new GenericType($index, $indexAnnotation->typeName); return $type; }
/** * @test */ public function classWithNoPropertyAnnotatedHasAllPropertiesToBeIndexed() { $actual = $this->informer->getClassProperties('Flowpack\\ElasticSearch\\Tests\\Functional\\Fixtures\\Tweet'); $this->assertGreaterThan(1, $actual); }
/** * Shows the status of the current mapping * * @param string $object Class name of a domain object. If given, will only work on this single object * @param boolean $conductUpdate Set to TRUE to conduct the required corrections * @param string $clientName The client name to use */ public function statusCommand($object = null, $conductUpdate = false, $clientName = null) { $result = new ErrorResult(); $client = $this->clientFactory->create($clientName); $classesAndAnnotations = $this->indexInformer->getClassesAndAnnotations(); if ($object !== null) { if (!isset($classesAndAnnotations[$object])) { $this->outputFormatted("Error: Object '<b>%s</b>' is not configured correctly, check the Indexable annotation.", array($object)); $this->quit(1); } $classesAndAnnotations = array($object => $classesAndAnnotations[$object]); } array_walk($classesAndAnnotations, function (Indexable $annotation, $className) use($result, $client, $conductUpdate) { $this->outputFormatted("Object [33m%s[0m", array($className), 4); $this->outputFormatted("Index <b>%s</b> Type <b>%s</b>", array($annotation->indexName, $annotation->typeName), 8); $count = $client->findIndex($annotation->indexName)->findType($annotation->typeName)->count(); if ($count === null) { $result->forProperty($className)->addError(new Error('ElasticSearch was unable to retrieve a count for the type "%s" at index "%s". Probably these don\' exist.', 1340289921, array($annotation->typeName, $annotation->indexName))); } $this->outputFormatted("Documents in Search: <b>%s</b>", array($count !== null ? $count : "[41mError[0m"), 8); try { $count = $this->persistenceManager->createQueryForType($className)->count(); } catch (\Exception $exception) { $count = null; $result->forProperty($className)->addError(new Error('The persistence backend was unable to retrieve a count for the type "%s". The exception message was "%s".', 1340290088, array($className, $exception->getMessage()))); } $this->outputFormatted("Documents in Persistence: <b>%s</b>", array($count !== null ? $count : "[41mError[0m"), 8); if (!$result->forProperty($className)->hasErrors()) { $states = $this->getModificationsNeededStatesAndIdentifiers($client, $className); if ($conductUpdate) { $inserted = 0; $updated = 0; foreach ($states[ObjectIndexer::ACTION_TYPE_CREATE] as $identifier) { try { $this->objectIndexer->indexObject($this->persistenceManager->getObjectByIdentifier($identifier, $className)); $inserted++; } catch (\Exception $exception) { $result->forProperty($className)->addError(new Error('An error occurred while trying to add an object to the ElasticSearch backend. The exception message was "%s".', 1340356330, array($exception->getMessage()))); } } foreach ($states[ObjectIndexer::ACTION_TYPE_UPDATE] as $identifier) { try { $this->objectIndexer->indexObject($this->persistenceManager->getObjectByIdentifier($identifier, $className)); $updated++; } catch (\Exception $exception) { $result->forProperty($className)->addError(new Error('An error occurred while trying to update an object to the ElasticSearch backend. The exception message was "%s".', 1340358590, array($exception->getMessage()))); } } $this->outputFormatted("Objects inserted: <b>%s</b>", array($inserted), 8); $this->outputFormatted("Objects updated: <b>%s</b>", array($updated), 8); } else { $this->outputFormatted("Modifications needed: <b>create</b> %d, <b>update</b> %d", array(count($states[ObjectIndexer::ACTION_TYPE_CREATE]), count($states[ObjectIndexer::ACTION_TYPE_UPDATE])), 8); } } }); if ($result->hasErrors()) { $this->outputLine(); $this->outputLine('The following errors occurred:'); /** @var $error \TYPO3\Flow\Error\Error */ foreach ($result->getFlattenedErrors() as $className => $errors) { foreach ($errors as $error) { $this->outputLine(); $this->outputFormatted("<b>[41mError[0m</b> for [33m%s[0m:", array($className), 8); $this->outputFormatted((string) $error, array(), 4); } } } }