Files
jobifygarden/app/Console/Commands/DeduplicateJobs.php
T

106 lines
3.1 KiB
PHP
Raw Normal View History

2026-04-03 00:29:05 +03:00
<?php
namespace App\Console\Commands;
use App\Models\Job;
use Illuminate\Console\Attributes\Description;
use Illuminate\Console\Attributes\Signature;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
#[Signature('jobs:deduplicate {--dry-run}')]
#[Description('Find and remove duplicate job listings based on fingerprint')]
class DeduplicateJobs extends Command
{
2026-05-01 23:33:15 +03:00
protected $signature = 'jobs:deduplicate {--dry-run}';
protected $description = 'Find and remove duplicate job listings based on fingerprint';
2026-04-03 00:29:05 +03:00
/**
* Execute the console command.
*/
public function handle(): int
{
$dryRun = $this->option('dry-run');
$this->info('Searching for duplicate job listings...');
$this->newLine();
// Find duplicates by fingerprint
$duplicates = $this->findDuplicates();
if ($duplicates->isEmpty()) {
$this->info('No duplicates found!');
return self::SUCCESS;
}
$this->warn("Found {$duplicates->count()} sets of duplicates.");
$this->newLine();
$removedCount = 0;
foreach ($duplicates as $duplicate) {
$fingerprint = $duplicate->fingerprint;
$count = $duplicate->count;
// Get all jobs with this fingerprint, ordered by created_at (keep oldest)
$jobs = Job::where('fingerprint', $fingerprint)
->orderBy('created_at', 'asc')
->get();
// Keep the first one, mark others for removal
$toKeep = $jobs->first();
$toRemove = $jobs->skip(1);
$this->line("Fingerprint: {$fingerprint}");
$this->line(" Keeping: #{$toKeep->id} - {$toKeep->title} ({$toKeep->source->name})");
foreach ($toRemove as $job) {
$this->line(" Removing: #{$job->id} - {$job->title} ({$job->source->name})");
if (!$dryRun) {
$job->delete();
$removedCount++;
}
}
$this->newLine();
}
if ($dryRun) {
$this->info("Dry run completed. Would remove {$this->countDuplicatesToRemove($duplicates)} duplicate jobs.");
$this->line('Run without --dry-run to actually remove them.');
} else {
$this->info("Removed {$removedCount} duplicate jobs.");
}
return self::SUCCESS;
}
/**
* Find duplicate fingerprints
*/
private function findDuplicates()
{
return DB::table('jobs')
->select('fingerprint', DB::raw('COUNT(*) as count'))
->whereNull('deleted_at')
->whereNotNull('fingerprint')
->groupBy('fingerprint')
->having('count', '>', 1)
->orderBy('count', 'desc')
->get();
}
/**
* Count total duplicates to remove
*/
private function countDuplicatesToRemove($duplicates): int
{
$total = 0;
foreach ($duplicates as $duplicate) {
$total += ($duplicate->count - 1); // Keep 1, remove the rest
}
return $total;
}
}