Merge pull request #331 from shikorism/fix/330-tag-dedup

メタデータのタグ重複対策
This commit is contained in:
shibafu 2020-05-16 15:00:51 +09:00 committed by GitHub
commit c11bbbbff7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 151 additions and 0 deletions

View File

@ -0,0 +1,113 @@
<?php
namespace App\Console\Commands;
use App\Tag;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class DedupTags extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tissue:tag:dedup {--dry-run}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Deduplicate tags';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
if ($this->option('dry-run')) {
$this->warn('dry-runモードで実行します。');
} else {
if (!$this->confirm('dry-runオプションが付いてないけど、本当に実行しますか')) {
return;
}
}
DB::transaction(function () {
$duplicatedTags = DB::table('tags')
->select('name', DB::raw('count(*)'))
->groupBy('name')
->having(DB::raw('count(*)'), '>=', 2)
->get();
$this->info($duplicatedTags->count() . ' duplicated tags found.');
foreach ($duplicatedTags as $tag) {
$this->line('Tag name: ' . $tag->name);
$tagIds = Tag::where('name', $tag->name)->orderBy('id')->pluck('id');
$newId = $tagIds->first();
$dropIds = $tagIds->slice(1);
$this->line(' New ID: ' . $newId);
$this->line(' Drop IDs: ' . $dropIds->implode(', '));
if ($this->option('dry-run')) {
continue;
}
// 同じタグ名でIDが違うものについて、全て統一する
foreach (['ejaculation_tag', 'metadata_tag'] as $table) {
DB::table($table)
->whereIn('tag_id', $dropIds)
->update(['tag_id' => $newId]);
}
DB::table('tags')->whereIn('id', $dropIds)->delete();
// 統一した上で、重複しているレコードを削除する
DB::delete(
<<<SQL
DELETE FROM ejaculation_tag
WHERE id IN (
SELECT id
FROM (
SELECT id, row_number() OVER (PARTITION BY ejaculation_id, tag_id ORDER BY id) AS ord
FROM ejaculation_tag
) t
WHERE ord > 1
)
SQL
);
DB::delete(
<<<SQL
DELETE FROM metadata_tag
WHERE id IN (
SELECT id
FROM (
SELECT id, row_number() OVER (PARTITION BY metadata_url, tag_id ORDER BY id) AS ord
FROM metadata_tag
) t
WHERE ord > 1
)
SQL
);
}
});
$this->info('Done!');
}
}

View File

@ -0,0 +1,38 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddUniqueConstraintToTagRelations extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('ejaculation_tag', function (Blueprint $table) {
$table->unique(['ejaculation_id', 'tag_id']);
});
Schema::table('metadata_tag', function (Blueprint $table) {
$table->unique(['metadata_url', 'tag_id']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('ejaculation_tag', function (Blueprint $table) {
$table->dropUnique(['ejaculation_id', 'tag_id']);
});
Schema::table('metadata_tag', function (Blueprint $table) {
$table->dropUnique(['metadata_url', 'tag_id']);
});
}
}