[!!!][FEATURE] Remap specific document type's to ES6 identifiers

Multiple types are not allowed any more in ES6. Refactored to use document type and custom
identifier to still create different 'types'.

See: https://www.elastic.co/guide/en/elasticsearch/reference/6.x/removal-of-types.html
This commit is contained in:
Benjamin Serfhos 2018-10-11 16:50:32 +02:00
parent 397a91e9b0
commit e297d556e6
6 changed files with 84 additions and 32 deletions

View file

@ -23,6 +23,7 @@ namespace Codappix\SearchCore\Command;
use Codappix\SearchCore\Domain\Index\IndexerFactory; use Codappix\SearchCore\Domain\Index\IndexerFactory;
use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException; use Codappix\SearchCore\Domain\Index\NoMatchingIndexerException;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Mvc\Controller\CommandController; use TYPO3\CMS\Extbase\Mvc\Controller\CommandController;
/** /**
@ -52,14 +53,19 @@ class IndexCommandController extends CommandController
*/ */
public function indexCommand(string $identifier) public function indexCommand(string $identifier)
{ {
// Allow multiple identifiers per import task
$identifiers = GeneralUtility::trimExplode(',', $identifier, true);
foreach ($identifiers as $value) {
try { try {
$this->indexerFactory->getIndexer($identifier)->indexAllDocuments(); $this->indexerFactory->getIndexer($value)->indexAllDocuments();
$this->outputLine($identifier . ' was indexed.'); $this->outputLine($value . ' was indexed.');
} catch (NoMatchingIndexerException $e) { } catch (NoMatchingIndexerException $e) {
$this->outputLine('No indexer found for: ' . $identifier); $this->outputLine('No indexer found for: ' . $value);
} }
} }
}
/** /**
* Will delete the given identifier. * Will delete the given identifier.
* *
@ -68,11 +74,15 @@ class IndexCommandController extends CommandController
*/ */
public function deleteCommand(string $identifier) public function deleteCommand(string $identifier)
{ {
// Allow multiple identifiers per import task
$identifiers = GeneralUtility::trimExplode(',', $identifier, true);
foreach ($identifiers as $value) {
try { try {
$this->indexerFactory->getIndexer($identifier)->delete(); $this->indexerFactory->getIndexer($value)->delete();
$this->outputLine($identifier . ' was deleted.'); $this->outputLine($value . ' was deleted.');
} catch (NoMatchingIndexerException $e) { } catch (NoMatchingIndexerException $e) {
$this->outputLine('No indexer found for: ' . $identifier); $this->outputLine('No indexer found for: ' . $value);
}
} }
} }
} }

View file

@ -21,6 +21,8 @@ namespace Codappix\SearchCore\Connection;
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use Elastica\Query;
/** /**
* Defines interface for connections to storage backend for interacting with documents. * Defines interface for connections to storage backend for interacting with documents.
*/ */
@ -77,8 +79,15 @@ interface ConnectionInterface
/** /**
* Will delete the whole index / db. * Will delete the whole index / db.
* *
* @param string $documentType
* @return void * @return void
*/ */
public function deleteIndex(string $documentType); public function deleteIndex();
/**
* Will delete the index / db of defined document type.
*
* @param Query $query
* @return void
*/
public function deleteIndexByQuery(Query $query);
} }

View file

@ -23,8 +23,10 @@ namespace Codappix\SearchCore\Connection;
use Codappix\SearchCore\Connection\Elasticsearch\SearchResult; use Codappix\SearchCore\Connection\Elasticsearch\SearchResult;
use Codappix\SearchCore\Domain\Search\QueryFactory; use Codappix\SearchCore\Domain\Search\QueryFactory;
use Elastica\Query;
use TYPO3\CMS\Core\SingletonInterface as Singleton; use TYPO3\CMS\Core\SingletonInterface as Singleton;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface; use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
use TYPO3\CMS\Extbase\Utility\DebuggerUtility;
/** /**
* Outer wrapper to elasticsearch. * Outer wrapper to elasticsearch.
@ -121,8 +123,8 @@ class Elasticsearch implements Singleton, ConnectionInterface
{ {
$this->withType( $this->withType(
$documentType, $documentType,
function ($type) use ($document) { function ($type) use ($documentType, $document) {
$type->addDocument($this->documentFactory->getDocument($type->getName(), $document)); $type->addDocument($this->documentFactory->getDocument($documentType, $document));
} }
); );
} }
@ -156,8 +158,8 @@ class Elasticsearch implements Singleton, ConnectionInterface
{ {
$this->withType( $this->withType(
$documentType, $documentType,
function ($type) use ($document) { function ($type) use ($documentType, $document) {
$type->updateDocument($this->documentFactory->getDocument($type->getName(), $document)); $type->updateDocument($this->documentFactory->getDocument($documentType, $document));
} }
); );
} }
@ -170,23 +172,23 @@ class Elasticsearch implements Singleton, ConnectionInterface
{ {
$this->withType( $this->withType(
$documentType, $documentType,
function ($type) use ($documents) { function ($type) use ($documentType, $documents) {
$type->addDocuments($this->documentFactory->getDocuments($type->getName(), $documents)); $type->addDocuments($this->documentFactory->getDocuments($documentType, $documents));
} }
); );
} }
/** /**
* @param string $documentType * @return void
*/ */
public function deleteIndex(string $documentType) public function deleteIndex()
{ {
$index = $this->connection->getClient()->getIndex($this->indexFactory->getIndexName()); $index = $this->connection->getClient()->getIndex($this->indexFactory->getIndexName());
if (!$index->exists()) { if (!$index->exists()) {
$this->logger->notice( $this->logger->notice(
'Index did not exist, therefore was not deleted.', 'Index did not exist, therefore was not deleted.',
[$documentType, $this->indexFactory->getIndexName()] [$this->indexFactory->getIndexName()]
); );
return; return;
} }
@ -194,6 +196,24 @@ class Elasticsearch implements Singleton, ConnectionInterface
$index->delete(); $index->delete();
} }
/**
* @param Query $query
* @return void
*/
public function deleteIndexByQuery(Query $query)
{
$index = $this->connection->getClient()->getIndex($this->indexFactory->getIndexName());
if (!$index->exists()) {
$this->logger->notice(
'Index did not exist, therefore items can not be deleted by query.',
[$this->indexFactory->getIndexName(), $query->getQuery()]
);
return;
}
$index->deleteByQuery($query);
}
/** /**
* Execute given callback with Elastica Type based on provided documentType * Execute given callback with Elastica Type based on provided documentType
* *
@ -202,7 +222,7 @@ class Elasticsearch implements Singleton, ConnectionInterface
*/ */
protected function withType(string $documentType, callable $callback) protected function withType(string $documentType, callable $callback)
{ {
$type = $this->getType($documentType); $type = $this->getType();
// TODO: Check whether it's to heavy to send it so often e.g. for every single document. // TODO: Check whether it's to heavy to send it so often e.g. for every single document.
// Perhaps add command controller to submit mapping?! // Perhaps add command controller to submit mapping?!
// Also it's not possible to change mapping without deleting index first. // Also it's not possible to change mapping without deleting index first.
@ -230,17 +250,16 @@ class Elasticsearch implements Singleton, ConnectionInterface
} }
/** /**
* @param string $documentType
* @return \Elastica\Type * @return \Elastica\Type
*/ */
protected function getType(string $documentType): \Elastica\Type protected function getType(): \Elastica\Type
{ {
return $this->typeFactory->getType( return $this->typeFactory->getType(
$this->indexFactory->getIndex( $this->indexFactory->getIndex(
$this->connection, $this->connection,
$documentType 'document'
), ),
$documentType 'document'
); );
} }
} }

View file

@ -60,7 +60,6 @@ class DocumentFactory implements Singleton
} }
$identifier = $document['search_identifier']; $identifier = $document['search_identifier'];
unset($document['search_identifier']);
$this->logger->debug( $this->logger->debug(
sprintf('Convert %s %u to document.', $documentType, $identifier), sprintf('Convert %s %u to document.', $documentType, $identifier),

View file

@ -24,6 +24,7 @@ namespace Codappix\SearchCore\Domain\Index;
use Codappix\SearchCore\Configuration\ConfigurationContainerInterface; use Codappix\SearchCore\Configuration\ConfigurationContainerInterface;
use Codappix\SearchCore\Configuration\InvalidArgumentException; use Codappix\SearchCore\Configuration\InvalidArgumentException;
use Codappix\SearchCore\Connection\ConnectionInterface; use Codappix\SearchCore\Connection\ConnectionInterface;
use Elastica\Query;
use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Core\Utility\GeneralUtility;
abstract class AbstractIndexer implements IndexerInterface abstract class AbstractIndexer implements IndexerInterface
@ -130,7 +131,13 @@ abstract class AbstractIndexer implements IndexerInterface
public function delete() public function delete()
{ {
$this->logger->info('Start deletion of index.'); $this->logger->info('Start deletion of index.');
$this->connection->deleteIndex($this->getDocumentName()); $this->connection->deleteIndexByQuery(Query::create([
'query' => [
'regexp' => [
'search_identifier' => $this->getDocumentName() . '-*'
]
]
]));
$this->logger->info('Finish deletion.'); $this->logger->info('Finish deletion.');
} }
@ -161,10 +168,21 @@ abstract class AbstractIndexer implements IndexerInterface
} catch (InvalidArgumentException $e) { } catch (InvalidArgumentException $e) {
// Nothing to do. // Nothing to do.
} }
$this->generateSearchIdentifier($record);
$this->handleAbstract($record); $this->handleAbstract($record);
} }
/**
* @param array $record
* @return void
*/
protected function generateSearchIdentifier(array &$record)
{
if (!isset($record['search_identifier']) && isset($record['uid'])) {
$record['search_identifier'] = $this->getDocumentName() . '-' . $record['uid'];
}
}
/** /**
* @param array $record * @param array $record
* @return void * @return void

View file

@ -168,9 +168,6 @@ class TcaTableService implements TcaTableServiceInterface
*/ */
public function prepareRecord(array &$record) public function prepareRecord(array &$record)
{ {
if (isset($record['uid']) && !isset($record['search_identifier'])) {
$record['search_identifier'] = $record['uid'];
}
if (isset($record[$this->tca['ctrl']['label']]) && !isset($record['search_title'])) { if (isset($record[$this->tca['ctrl']['label']]) && !isset($record['search_title'])) {
$record['search_title'] = $record[$this->tca['ctrl']['label']]; $record['search_title'] = $record[$this->tca['ctrl']['label']];
} }