Skip to content

Commit

Permalink
Merge pull request #1 from triadev/field_datatype_migration
Browse files Browse the repository at this point in the history
Validate the update index mapping changes.
  • Loading branch information
triadev committed Sep 18, 2018
2 parents b45cf0e + f208679 commit 2ea4bba
Show file tree
Hide file tree
Showing 9 changed files with 337 additions and 5 deletions.
4 changes: 0 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ php:
- 7.1
- 7.2

branches:
only:
- master

env:
matrix:
- "ES_VERSION=6.0.0 ES_DOWNLOAD_URL=https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.0.0.deb"
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"require": {
"php": ">=7.1",
"laravel/framework": "5.5.* || 5.6.* || 5.7.*",
"elasticsearch/elasticsearch": "^6.0"
"elasticsearch/elasticsearch": "^6.0",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "^6.0 || ^7.0",
Expand Down
11 changes: 11 additions & 0 deletions src/Business/Migration/UpdateIndex.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
namespace Triadev\EsMigration\Business\Migration;

use Elasticsearch\Client;
use Triadev\EsMigration\Business\Validation\FieldDatatypeMigration;
use Triadev\EsMigration\Exception\FieldDatatypeMigrationFailed;
use Triadev\EsMigration\Models\Migration;

class UpdateIndex
Expand All @@ -11,11 +13,20 @@ class UpdateIndex
*
* @param Client $esClient
* @param Migration $migration
*
* @throws FieldDatatypeMigrationFailed
*/
public function migrate(Client $esClient, Migration $migration)
{
if ($migration->getType() == 'update') {
if ($migration->getMappings()) {
(new FieldDatatypeMigration())->validate(
$esClient->indices()->getMapping(
['index' => $migration->getIndex()]
)[$migration->getIndex()]['mappings'],
$migration->getMappings()
);

$this->updateMappings($esClient, $migration);
}

Expand Down
111 changes: 111 additions & 0 deletions src/Business/Validation/FieldDatatypeMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<?php
namespace Triadev\EsMigration\Business\Validation;

use Triadev\EsMigration\Exception\FieldDatatypeMigrationFailed;

class FieldDatatypeMigration
{
/** @var array */
private $string = ['text', 'keyword'];

/** @var array */
private $numeric = ['long', 'integer', 'short', 'byte', 'double', 'float', 'half_float', 'scaled_float'];

/** @var array */
private $date = ['date'];

/** @var array */
private $boolean = ['boolean'];

/** @var array */
private $binary = ['binary'];

/** @var array */
private $range = ['integer_range', 'float_range', 'long_range', 'double_range', 'date_range'];

/** @var array */
private $validMigrations = [
'string' => [],
'numeric' => ['string'],
'date' => ['string'],
'boolean' => ['string'],
'binary' => [],
'range' => [],
'object' => [],
'nested' => [],
'geo_point' => [],
'geo_shape' => [],
'ip' => [],
'completion' => [],
'token_count' => [],
'murmur3' => [],
'attachment' => [],
'percolator' => []
];

/**
* Validate
*
* @param array $esMapping
* @param array $migrationMapping
*
* @throws FieldDatatypeMigrationFailed
*/
public function validate(array $esMapping, array $migrationMapping)
{
$tmpEsMapping = array_dot($esMapping);
$tmpMigrationMapping = array_dot($migrationMapping);

$failedFields = [];

foreach ($tmpEsMapping as $key => $value) {
if (preg_match('/^.*type$/', $key) && array_key_exists($key, $tmpMigrationMapping)) {
$esMappingDatatype = $this->getFieldDatatype($tmpEsMapping[$key]);
$migrationMappingDatatype = $this->getFieldDatatype($tmpMigrationMapping[$key]);

if ($esMappingDatatype == $migrationMappingDatatype) {
continue;
}

if (!in_array($migrationMappingDatatype, $this->validMigrations[$esMappingDatatype])) {
$failedFields[] = $key;
continue;
}
}
}

if (!empty($failedFields)) {
throw new FieldDatatypeMigrationFailed(json_encode($failedFields));
}
}

private function getFieldDatatype(string $datatype) : ?string
{
$datatypes = [
'string' => $this->string,
'numeric' => $this->numeric,
'date' => $this->date,
'boolean' => $this->boolean,
'binary' => $this->binary,
'range' => $this->range,
'object' => ['object'],
'nested' => ['nested'],
'geo_point' => ['geo_point'],
'geo_shape' => ['geo_shape'],
'ip' => ['ip'],
'completion' => ['completion'],
'token_count' => ['token_count'],
'murmur3' => ['murmur3'],
'attachment' => ['attachment'],
'percolator' => ['percolator']
];

foreach ($datatypes as $key => $d) {
if (in_array($datatype, $d)) {
return $key;
}
}

return null;
}
}
2 changes: 2 additions & 0 deletions src/Contract/ElasticsearchMigrationContract.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?php
namespace Triadev\EsMigration\Contract;

use Triadev\EsMigration\Exception\FieldDatatypeMigrationFailed;
use Triadev\EsMigration\Exception\MigrationAlreadyDone;

interface ElasticsearchMigrationContract
Expand All @@ -11,6 +12,7 @@ interface ElasticsearchMigrationContract
* @param string $version
*
* @throws MigrationAlreadyDone
* @throws FieldDatatypeMigrationFailed
* @throws \Throwable
*/
public function migrate(string $version);
Expand Down
18 changes: 18 additions & 0 deletions src/Exception/FieldDatatypeMigrationFailed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
namespace Triadev\EsMigration\Exception;

use Throwable;

class FieldDatatypeMigrationFailed extends \Exception
{
/**
* FieldDatatypeMigrationFailed constructor.
* @param string $message
* @param int $code
* @param Throwable|null $previous
*/
public function __construct(string $message = "", int $code = 0, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

return [
[
'index' => 'phpunit',
'type' => 'update',
'mappings' => [
'phpunit' => [
'properties' => [
'title' => [
'type' => 'integer'
],
'count' => [
'type' => 'text'
],
'description' => [
'type' => 'integer'
]
]
]
]
]
];
142 changes: 142 additions & 0 deletions tests/integration/Business/Validation/FieldDatatypeMigrationTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php
namespace Tests\Integration\Business\Validation;

use Tests\TestCase;
use Triadev\EsMigration\Exception\FieldDatatypeMigrationFailed;

class FieldDatatypeMigrationTest extends TestCase
{
/**
* @test
* @expectedException \Triadev\EsMigration\Exception\FieldDatatypeMigrationFailed
*/
public function it_validates_field_datatype_migrations()
{
$esMapping = [
'phpunit' => [
'properties' => [
'text' => [
'type' => 'text'
],
'keyword' => [
'type' => 'keyword'
],
'date' => [
'type' => 'date'
],
'boolean' => [
'type' => 'boolean'
],
'binary' => [
'type' => 'binary'
],
'range' => [
'type' => 'integer_range'
],
'object' => [
'type' => 'object'
],
'nested' => [
'type' => 'nested'
],
'geo_point' => [
'type' => 'geo_point'
],
'geo_shape' => [
'type' => 'geo_shape'
],
'ip' => [
'type' => 'ip'
],
'completion' => [
'type' => 'completion'
],
'token_count' => [
'type' => 'token_count'
],
'murmur3' => [
'type' => 'murmur3'
],
'attachment' => [
'type' => 'attachment'
],
'percolator' => [
'type' => 'percolator'
],
'valid' => [
'type' => 'text'
]
]
]
];

$migrationMapping = [
'phpunit' => [
'properties' => [
'text' => [
'type' => 'long'
],
'keyword' => [
'type' => 'long'
],
'date' => [
'type' => 'long'
],
'boolean' => [
'type' => 'long'
],
'binary' => [
'type' => 'long'
],
'range' => [
'type' => 'long'
],
'object' => [
'type' => 'long'
],
'nested' => [
'type' => 'long'
],
'geo_point' => [
'type' => 'long'
],
'geo_shape' => [
'type' => 'long'
],
'ip' => [
'type' => 'long'
],
'completion' => [
'type' => 'long'
],
'token_count' => [
'type' => 'long'
],
'murmur3' => [
'type' => 'long'
],
'attachment' => [
'type' => 'long'
],
'percolator' => [
'type' => 'long'
],
'valid' => [
'type' => 'keyword'
]
]
]
];

try {
(new \Triadev\EsMigration\Business\Validation\FieldDatatypeMigration())->validate(
$esMapping,
$migrationMapping
);
} catch (FieldDatatypeMigrationFailed $e) {
$this->assertCount(16, json_decode($e->getMessage()));

throw $e;
}
}
}
Loading

0 comments on commit 2ea4bba

Please sign in to comment.