Skip to content
This repository was archived by the owner on Nov 4, 2021. It is now read-only.

Commit d90a7e8

Browse files
committed
- Refactoring
- Migrate command - Tests for migrate command
1 parent a46a511 commit d90a7e8

8 files changed

+585
-5
lines changed

src/Console/ElasticIndexCreateCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Illuminate\Console\Command;
66
use ScoutElastic\Console\Features\requiresIndexConfiguratorArgument;
77
use ScoutElastic\Facades\ElasticClient;
8+
use ScoutElastic\Migratable;
89
use ScoutElastic\Payloads\IndexPayload;
910

1011
class ElasticIndexCreateCommand extends Command
@@ -37,7 +38,7 @@ protected function createWriteAlias()
3738
{
3839
$configurator = $this->getIndexConfigurator();
3940

40-
if (!method_exists($configurator, 'getWriteAlias')) {
41+
if (!in_array(Migratable::class, class_uses_recursive($configurator))) {
4142
return;
4243
}
4344

src/Console/ElasticIndexUpdateCommand.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Illuminate\Console\Command;
88
use ScoutElastic\Console\Features\requiresIndexConfiguratorArgument;
99
use ScoutElastic\Facades\ElasticClient;
10+
use ScoutElastic\Migratable;
1011
use ScoutElastic\Payloads\IndexPayload;
1112
use ScoutElastic\Payloads\RawPayload;
1213

@@ -70,7 +71,7 @@ protected function createWriteAlias()
7071
{
7172
$configurator = $this->getIndexConfigurator();
7273

73-
if (!method_exists($configurator, 'getWriteAlias')) {
74+
if (!in_array(Migratable::class, class_uses_recursive($configurator))) {
7475
return;
7576
}
7677

src/Console/ElasticMigrateCommand.php

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
<?php
2+
3+
namespace ScoutElastic\Console;
4+
5+
use Exception;
6+
use Illuminate\Console\Command;
7+
use Illuminate\Support\Facades\Artisan;
8+
use ScoutElastic\Console\Features\requiresModelArgument;
9+
use ScoutElastic\Facades\ElasticClient;
10+
use ScoutElastic\Migratable;
11+
use ScoutElastic\Payloads\IndexPayload;
12+
use ScoutElastic\Payloads\RawPayload;
13+
use Symfony\Component\Console\Input\InputArgument;
14+
15+
class ElasticMigrateCommand extends Command
16+
{
17+
use requiresModelArgument {
18+
requiresModelArgument::getArguments as private modelArgument;
19+
}
20+
21+
protected $name = 'elastic:migrate';
22+
23+
protected $description = 'Migrate model to another index';
24+
25+
protected function getArguments()
26+
{
27+
$arguments = $this->modelArgument();
28+
29+
$arguments[] = ['target-index', InputArgument::REQUIRED, 'The index name to migrate'];
30+
31+
return $arguments;
32+
}
33+
34+
protected function isTargetIndexExists()
35+
{
36+
$targetIndex = $this->argument('target-index');
37+
38+
$payload = (new RawPayload())
39+
->set('index', $targetIndex)
40+
->get();
41+
42+
return ElasticClient::indices()
43+
->exists($payload);
44+
}
45+
46+
protected function createTargetIndex()
47+
{
48+
$targetIndex = $this->argument('target-index');
49+
50+
$sourceIndexConfigurator = $this->getModel()
51+
->getIndexConfigurator();
52+
53+
$payload = (new RawPayload())
54+
->set('index', $targetIndex)
55+
->setIfNotEmpty('body.settings', $sourceIndexConfigurator->getSettings())
56+
->setIfNotEmpty('body.mappings._default_', $sourceIndexConfigurator->getDefaultMapping())
57+
->get();
58+
59+
ElasticClient::indices()
60+
->create($payload);
61+
62+
$this->info(sprintf(
63+
'The index %s was created!',
64+
$targetIndex
65+
));
66+
}
67+
68+
protected function updateTargetIndex()
69+
{
70+
$targetIndex = $this->argument('target-index');
71+
72+
$sourceIndexConfigurator = $this->getModel()
73+
->getIndexConfigurator();
74+
75+
$targetIndexPayload = (new RawPayload())
76+
->set('index', $targetIndex)
77+
->get();
78+
79+
$indices = ElasticClient::indices();
80+
81+
try {
82+
$indices->close($targetIndexPayload);
83+
84+
if ($settings = $sourceIndexConfigurator->getSettings()) {
85+
$targetIndexSettingsPayload = (new RawPayload())
86+
->set('index', $targetIndex)
87+
->set('body.settings', $settings)
88+
->get();
89+
90+
$indices->putSettings($targetIndexSettingsPayload);
91+
}
92+
93+
if ($defaultMapping = $sourceIndexConfigurator->getDefaultMapping()) {
94+
$targetIndexMappingPayload = (new RawPayload())
95+
->set('index', $targetIndex)
96+
->set('type', '_default_')
97+
->set('body._default_', $defaultMapping)
98+
->get();
99+
100+
$indices->putMapping($targetIndexMappingPayload);
101+
}
102+
103+
$indices->open($targetIndexPayload);
104+
} catch (Exception $exception) {
105+
$indices->open($targetIndexPayload);
106+
107+
throw $exception;
108+
}
109+
110+
$this->info(sprintf(
111+
'The index %s was updated!',
112+
$targetIndex
113+
));
114+
}
115+
116+
protected function updateTargetIndexMapping()
117+
{
118+
$sourceModel = $this->getModel();
119+
$sourceIndexConfigurator = $sourceModel->getIndexConfigurator();
120+
121+
$targetIndex = $this->argument('target-index');
122+
$targetType = $sourceModel->searchableAs();
123+
124+
$mapping = array_merge_recursive(
125+
$sourceIndexConfigurator->getDefaultMapping(),
126+
$sourceModel->getMapping()
127+
);
128+
129+
if (empty($mapping)) {
130+
$this->warn(sprintf(
131+
'The %s mapping is empty.',
132+
get_class($sourceModel)
133+
));
134+
135+
return;
136+
}
137+
138+
$payload = (new RawPayload())
139+
->set('index', $targetIndex)
140+
->set('type', $targetType)
141+
->set('body.'.$targetType, $mapping)
142+
->get();
143+
144+
ElasticClient::indices()
145+
->putMapping($payload);
146+
147+
$this->info(sprintf(
148+
'The %s mapping was updated!',
149+
$targetIndex
150+
));
151+
}
152+
153+
protected function isAliasExists($name)
154+
{
155+
$payload = (new RawPayload())
156+
->set('name', $name)
157+
->get();
158+
159+
return ElasticClient::indices()
160+
->existsAlias($payload);
161+
}
162+
163+
protected function deleteAlias($name)
164+
{
165+
$indices = ElasticClient::indices();
166+
167+
$getPayload = (new RawPayload())
168+
->set('name', $name)
169+
->get();
170+
171+
$aliases = $indices->getAlias($getPayload);
172+
173+
if (empty($aliases)) {
174+
return;
175+
}
176+
177+
foreach ($aliases as $index => $alias) {
178+
$deletePayload = (new RawPayload())
179+
->set('index', $index)
180+
->set('name', $name)
181+
->get();
182+
183+
$indices->deleteAlias($deletePayload);
184+
185+
$this->info(sprintf(
186+
'The %s alias for the %s index was deleted.',
187+
$name,
188+
$index
189+
));
190+
}
191+
}
192+
193+
protected function createAliasForTargetIndex($name)
194+
{
195+
$targetIndex = $this->argument('target-index');
196+
197+
if ($this->isAliasExists($name)) {
198+
$this->deleteAlias($name);
199+
}
200+
201+
$payload = (new RawPayload())
202+
->set('index', $targetIndex)
203+
->set('name', $name)
204+
->get();
205+
206+
ElasticClient::indices()
207+
->putAlias($payload);
208+
209+
$this->info(sprintf(
210+
'The %s alias for the %s index was created.',
211+
$name,
212+
$targetIndex
213+
));
214+
}
215+
216+
protected function importDocumentsToTargetIndex()
217+
{
218+
$sourceModel = $this->getModel();
219+
220+
Artisan::call(
221+
'scout:import',
222+
['model' => get_class($sourceModel)]
223+
);
224+
}
225+
226+
protected function deleteSourceIndex()
227+
{
228+
$sourceIndexConfigurator = $this->getModel()
229+
->getIndexConfigurator();
230+
231+
$payload = (new IndexPayload($sourceIndexConfigurator))
232+
->get();
233+
234+
ElasticClient::indices()
235+
->delete($payload);
236+
237+
$this->info(sprintf(
238+
'The %s index was removed.',
239+
$sourceIndexConfigurator->getName()
240+
));
241+
}
242+
243+
public function handle()
244+
{
245+
$sourceModel = $this->getModel();
246+
$sourceIndexConfigurator = $sourceModel->getIndexConfigurator();
247+
248+
if (!in_array(Migratable::class, class_uses_recursive($sourceIndexConfigurator))) {
249+
$this->error(sprintf(
250+
'The %s index configurator must use the %s trait.',
251+
get_class($sourceIndexConfigurator),
252+
Migratable::class
253+
));
254+
255+
return;
256+
}
257+
258+
$this->isTargetIndexExists() ? $this->updateTargetIndex() : $this->createTargetIndex();
259+
260+
$this->updateTargetIndexMapping();
261+
262+
$this->createAliasForTargetIndex($sourceIndexConfigurator->getWriteAlias());
263+
264+
$this->importDocumentsToTargetIndex();
265+
266+
$this->deleteSourceIndex();
267+
268+
$this->createAliasForTargetIndex($sourceIndexConfigurator->getName());
269+
270+
$this->info(sprintf(
271+
'The %s model successfully migrated to the %s index.',
272+
get_class($sourceModel),
273+
$this->argument('target-index')
274+
));
275+
}
276+
}

src/Console/Features/requiresModelArgument.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected function getModel()
1818

1919
$modelInstance = new $modelClass;
2020

21-
if (!($modelInstance instanceof Model) || !method_exists($modelInstance, 'getIndexConfigurator')) {
21+
if (!($modelInstance instanceof Model) || !in_array(Searchable::class, class_uses_recursive($modelClass))) {
2222
throw new InvalidArgumentException(sprintf(
2323
'The %s class must extend %s and use the %s trait.',
2424
$modelClass,

src/ElasticEngine.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ public function update($models)
3737
$payload = (new DocumentPayload($model))
3838
->setIfNotEmpty('body', $model->toSearchableArray());
3939

40-
if (method_exists($indexConfigurator, 'getWriteAlias')) {
40+
if (in_array(Migratable::class, class_uses_recursive($indexConfigurator))) {
4141
$payload->useAlias('write');
4242
}
4343

src/Payloads/TypePayload.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class TypePayload extends IndexPayload
1717

1818
public function __construct(Model $model)
1919
{
20-
if (!method_exists($model, 'getIndexConfigurator')) {
20+
if (!in_array(Searchable::class, class_uses_recursive($model))) {
2121
throw new Exception(sprintf(
2222
'The %s model must use the %s trait.',
2323
get_class($model),

src/ScoutElasticServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use ScoutElastic\Console\ElasticIndexCreateCommand;
99
use ScoutElastic\Console\ElasticIndexDropCommand;
1010
use ScoutElastic\Console\ElasticIndexUpdateCommand;
11+
use ScoutElastic\Console\ElasticMigrateCommand;
1112
use ScoutElastic\Console\ElasticUpdateMappingCommand;
1213
use ScoutElastic\Console\IndexConfiguratorMakeCommand;
1314
use ScoutElastic\Console\SearchableModelMakeCommand;
@@ -33,6 +34,7 @@ public function boot()
3334
ElasticIndexUpdateCommand::class,
3435
ElasticIndexDropCommand::class,
3536
ElasticUpdateMappingCommand::class,
37+
ElasticMigrateCommand::class
3638
]);
3739

3840
$this->app->make(EngineManager::class)

0 commit comments

Comments
 (0)