Created
February 2, 2017 21:43
-
-
Save andrewmclagan/7525400afe2e6ecd74c432e7ca40fd41 to your computer and use it in GitHub Desktop.
Elasticsearch indexer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace App\Services; | |
| use Illuminate\Support\Collection; | |
| use Illuminate\Database\Eloquent\Model; | |
| use Elasticsearch\Client; | |
| use App\Models; | |
| /** | |
| * Indexes documents in elasticsearch | |
| * | |
| * @author Andrew McLagan <andrew@ethicaljobs.com.au> | |
| */ | |
| class ElasticsearchIndexer | |
| { | |
| /** | |
| * Elastic search client | |
| * | |
| * @param \Elasticsearch\Client | |
| */ | |
| private $elasticsearch; | |
| /** | |
| * Elastic search index | |
| * | |
| * @param String | |
| */ | |
| private $index; | |
| /** | |
| * Size of collection request chunks | |
| * | |
| * @param Integer | |
| */ | |
| private $chunkSize; | |
| /** | |
| * Indexable eloquent models | |
| * | |
| * @param Array | |
| */ | |
| public $indexableModels = [ | |
| Models\Job::class, | |
| ]; | |
| /** | |
| * Constructor | |
| * | |
| * @param \Elasticsearch\Client $elasticsearch | |
| * @return void | |
| */ | |
| public function __construct(Client $elasticsearch, $chunkSize = 125) | |
| { | |
| $this->elasticsearch = $elasticsearch; | |
| $this->chunkSize = $chunkSize; | |
| $this->index = config('elasticsearch.index'); | |
| } | |
| /** | |
| * Indexes a single model instance | |
| * | |
| * @param \App\Models\Model $entity | |
| * @return Array | |
| */ | |
| public function indexEntity(Model $entity) | |
| { | |
| $params = $this->getParamsByEntity($entity); | |
| return $this->elasticsearch->index($params); | |
| } | |
| /** | |
| * Removes a document from the index | |
| * | |
| * @param \App\Models\Model $entity | |
| * @return Array | |
| */ | |
| public function deleteEntity(Model $entity) | |
| { | |
| $params = $this->getParamsByEntity($entity, true); | |
| return $this->elasticsearch->delete($params); | |
| } | |
| /** | |
| * Indexes a collection of entities | |
| * | |
| * @param \Illuminate\Support\Collection $collection | |
| * @return Array | |
| */ | |
| public function indexCollection(Collection $collection) | |
| { | |
| return $this->collectionOperation($collection, false); | |
| } | |
| /** | |
| * Removes a collection of entities from the index | |
| * | |
| * @param \Illuminate\Support\Collection $collection | |
| * @return Array | |
| */ | |
| public function deleteCollection(Collection $collection) | |
| { | |
| return $this->collectionOperation($collection, true); | |
| } | |
| /** | |
| * Indexes all model entities by eloquent class | |
| * | |
| * @param String $class | |
| * @return Void | |
| */ | |
| public function indexAllEntities($class) | |
| { | |
| if ($collection = $this->getModelEntities($class)) { | |
| $this->indexCollection($collection); | |
| } | |
| } | |
| /** | |
| * Remove all model entities by eloquent class | |
| * | |
| * @param String $class | |
| * @return Void | |
| */ | |
| public function deleteAllEntities($class) | |
| { | |
| if ($collection = $this->getModelEntities($class)) { | |
| $this->deleteCollection($collection); | |
| } | |
| } | |
| /** | |
| * Indexes entire database | |
| * | |
| * @return Void | |
| */ | |
| public function indexAll() | |
| { | |
| foreach ($this->indexableModels as $class) { | |
| $this->indexAllEntities($class); | |
| } | |
| } | |
| /** | |
| * Removes all documents from elasticsearch | |
| * | |
| * @return Void | |
| */ | |
| public function deleteAll() | |
| { | |
| return $this->elasticsearch->indices()->delete([ | |
| 'index' => $this->index, | |
| ]); | |
| } | |
| /** | |
| * Runs an operation on a collection | |
| * | |
| * @param \Illuminate\Support\Collection $collection | |
| * @param Boolean $delete | |
| * @return Array | |
| */ | |
| protected function collectionOperation(Collection $collection, $delete = false) | |
| { | |
| $chunks = $collection->chunk($this->chunkSize); | |
| $results = []; | |
| $counter = 1; | |
| $totalChunks = $chunks->count(); | |
| dump("Chunks discovered: {$chunks->count()} with a size of: {$this->chunkSize}"); | |
| foreach ($chunks as $chunk) { | |
| dump("Executing chunk: {$counter}/{$totalChunks}"); | |
| $params = $this->getParamsByCollection($chunk, $delete); | |
| $result = $this->elasticsearch->bulk($params); | |
| $results = array_merge($results, $result); // this is faulty we need a proper merge routine. | |
| $counter++; | |
| } | |
| return $results; | |
| } | |
| /** | |
| * Gets all entities of an indexable model | |
| * | |
| * @return Void | |
| */ | |
| protected function getModelEntities($class) | |
| { | |
| dump("Fetching indexable entities: {$class}"); | |
| return (new $class) | |
| ->newQuery() | |
| ->withoutGlobalScopes() | |
| ->get(['*']); | |
| } | |
| /** | |
| * Creates parameters from a single entity | |
| * | |
| * @param \App\Models\Model $entity | |
| * @param Bool $delete | |
| * @return Array | |
| */ | |
| protected function getParamsByEntity($entity, $delete = false) | |
| { | |
| $params = [ | |
| 'index' => $this->index, | |
| 'id' => $entity->id, | |
| 'type' => $entity->getTable(), | |
| 'body' => $entity->toArray(), | |
| ]; | |
| return $delete ? array_except($params, 'body') : $params; | |
| } | |
| /** | |
| * Creates parameters from a collection of entities | |
| * | |
| * @param \Illuminate\Support\Collection $entity | |
| * @param Bool $delete | |
| * @return Array | |
| */ | |
| protected function getParamsByCollection(Collection $collection, $delete = false) | |
| { | |
| $actionKey = $delete ? 'delete' : 'index'; | |
| $params = []; | |
| foreach ($collection as $entity) { | |
| $params['body'][] = [ | |
| $actionKey => [ | |
| '_id' => $entity->id, | |
| '_type' => $entity->getTable(), | |
| '_index' => $this->index, | |
| ], | |
| ]; | |
| if (! $delete) { | |
| $params['body'][] = $entity->toArray(); | |
| } | |
| } | |
| return $params; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment