Initial commit
This commit is contained in:
246
database/seeders/TestSearchDataSeeder.php
Normal file
246
database/seeders/TestSearchDataSeeder.php
Normal file
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Call;
|
||||
use App\Models\CallTranslation;
|
||||
use App\Models\Locations\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Temporary seeder for search testing only. NOT for production.
|
||||
* Assigns random tags and calls to users that don't have them.
|
||||
*
|
||||
* Run: php artisan db:seed --class=TestSearchDataSeeder
|
||||
* Undo: php artisan db:seed --class=TestSearchDataSeeder --rollback
|
||||
* (or pass --rollback flag)
|
||||
*/
|
||||
class TestSearchDataSeeder extends Seeder
|
||||
{
|
||||
// How many users to seed (pick randomly from those without tags/calls)
|
||||
private const USERS_TO_SEED = 200;
|
||||
private const TAGS_PER_USER = 3;
|
||||
private const CALLS_PER_USER = 2;
|
||||
|
||||
public function run(bool $rollback = false): void
|
||||
{
|
||||
if ($rollback || in_array('--rollback', $_SERVER['argv'] ?? [])) {
|
||||
$this->rollback();
|
||||
return;
|
||||
}
|
||||
|
||||
$this->seedTags();
|
||||
$this->seedCalls();
|
||||
|
||||
$this->command->info('Re-indexing affected users in Elasticsearch (synchronously)...');
|
||||
$this->reindexAffectedUsers();
|
||||
$this->command->info('Done. Run with --rollback to remove test data.');
|
||||
}
|
||||
|
||||
private function seedTags(): void
|
||||
{
|
||||
$users = User::doesntHave('tags')
|
||||
->inRandomOrder()
|
||||
->limit(self::USERS_TO_SEED)
|
||||
->get();
|
||||
|
||||
// Only use tag_ids that have a context with a non-null category_id
|
||||
$tagIds = DB::table('taggable_contexts')
|
||||
->whereNotNull('category_id')
|
||||
->inRandomOrder()->limit(500)->pluck('id')->toArray();
|
||||
|
||||
if (empty($tagIds)) {
|
||||
$this->command->warn('No tags found, skipping tag seeding.');
|
||||
return;
|
||||
}
|
||||
|
||||
$rows = [];
|
||||
$now = now()->toDateTimeString();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$selected = collect($tagIds)->shuffle()->take(self::TAGS_PER_USER);
|
||||
foreach ($selected as $tagId) {
|
||||
$rows[] = [
|
||||
'tag_id' => $tagId,
|
||||
'taggable_id' => $user->id,
|
||||
'taggable_type' => 'App\Models\User',
|
||||
'created_at' => $now,
|
||||
'updated_at' => $now,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Insert in chunks, ignore duplicates
|
||||
foreach (array_chunk($rows, 500) as $chunk) {
|
||||
DB::table('taggable_taggables')->insertOrIgnore($chunk);
|
||||
}
|
||||
|
||||
$this->command->info('Seeded tags for ' . $users->count() . ' users.');
|
||||
}
|
||||
|
||||
private function seedCalls(): void
|
||||
{
|
||||
$users = User::with(['locations.country', 'locations.division', 'locations.city', 'locations.district'])
|
||||
->inRandomOrder()
|
||||
->limit(self::USERS_TO_SEED)
|
||||
->get();
|
||||
|
||||
// Only use tag_ids that exist in taggable_tags AND have a context with a non-null category_id
|
||||
$validTagIds = DB::table('taggable_tags')
|
||||
->whereIn('tag_id', DB::table('taggable_contexts')->whereNotNull('category_id')->pluck('id'))
|
||||
->inRandomOrder()->limit(100)->pluck('tag_id')->toArray();
|
||||
|
||||
if (empty($validTagIds)) {
|
||||
$this->command->warn('No valid tags found, skipping call seeding.');
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch tag names for generating content
|
||||
$tagNames = DB::table('taggable_tags')
|
||||
->whereIn('tag_id', $validTagIds)
|
||||
->pluck('name', 'tag_id');
|
||||
|
||||
$count = 0;
|
||||
$now = now();
|
||||
|
||||
foreach ($users as $user) {
|
||||
$selected = collect($validTagIds)->shuffle()->take(self::CALLS_PER_USER);
|
||||
|
||||
// Resolve location from user's primary location
|
||||
$locationId = $this->resolveUserLocation($user);
|
||||
|
||||
foreach ($selected as $tagId) {
|
||||
// Random till date between 1 and 3 months from now
|
||||
$tillMonths = rand(1, 3);
|
||||
$till = $now->copy()->addMonths($tillMonths);
|
||||
|
||||
$call = Call::create([
|
||||
'callable_id' => $user->id,
|
||||
'callable_type' => 'App\Models\User',
|
||||
'tag_id' => $tagId,
|
||||
'location_id' => $locationId,
|
||||
'from' => $now->utc(),
|
||||
'till' => $till,
|
||||
'is_public' => true,
|
||||
'is_suppressed' => false,
|
||||
'is_paused' => false,
|
||||
]);
|
||||
|
||||
$tagName = $tagNames[$tagId] ?? 'this skill';
|
||||
CallTranslation::create([
|
||||
'call_id' => $call->id,
|
||||
'locale' => 'en',
|
||||
'content' => "Looking to connect with others around {$tagName}. Available for the coming months.",
|
||||
]);
|
||||
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
$this->command->info("Seeded {$count} calls for " . $users->count() . ' users.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve or create a standalone Location record from the user's primary location.
|
||||
*/
|
||||
private function resolveUserLocation(User $user): ?int
|
||||
{
|
||||
$userLocation = $user->locations->first();
|
||||
if (!$userLocation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$attributes = array_filter([
|
||||
'country_id' => $userLocation->country_id ?: null,
|
||||
'division_id' => $userLocation->division_id ?: null,
|
||||
'city_id' => $userLocation->city_id ?: null,
|
||||
'district_id' => $userLocation->district_id ?: null,
|
||||
]);
|
||||
|
||||
if (empty($attributes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Find existing standalone Location (no locatable_id/type) or create one
|
||||
$location = Location::whereNull('locatable_id')
|
||||
->whereNull('locatable_type')
|
||||
->where($attributes)
|
||||
->first();
|
||||
|
||||
if (!$location) {
|
||||
$location = new Location($attributes);
|
||||
$location->save();
|
||||
}
|
||||
|
||||
return $location->id;
|
||||
}
|
||||
|
||||
private function reindexAffectedUsers(): void
|
||||
{
|
||||
// Disable queue so indexing happens synchronously with full relationship loading
|
||||
config(['scout.queue' => false]);
|
||||
|
||||
$cutoff = now()->subMinutes(10)->toDateTimeString();
|
||||
$userIds = DB::table('taggable_taggables')
|
||||
->where('taggable_type', 'App\Models\User')
|
||||
->where('created_at', '>=', $cutoff)
|
||||
->pluck('taggable_id')
|
||||
->merge(
|
||||
DB::table('calls')->where('created_at', '>=', $cutoff)->pluck('callable_id')
|
||||
)
|
||||
->unique();
|
||||
|
||||
$bar = $this->command->getOutput()->createProgressBar($userIds->count());
|
||||
User::whereIn('id', $userIds)->each(function (User $user) use ($bar) {
|
||||
$user->searchable();
|
||||
$bar->advance();
|
||||
});
|
||||
$bar->finish();
|
||||
$this->command->newLine();
|
||||
|
||||
// Also re-index the calls themselves
|
||||
$this->command->info('Re-indexing calls in Elasticsearch...');
|
||||
config(['scout.queue' => false]);
|
||||
$callIds = DB::table('calls')->where('created_at', '>=', $cutoff)->pluck('id');
|
||||
$callBar = $this->command->getOutput()->createProgressBar($callIds->count());
|
||||
Call::whereIn('id', $callIds)->each(function (Call $call) use ($callBar) {
|
||||
$call->searchable();
|
||||
$callBar->advance();
|
||||
});
|
||||
$callBar->finish();
|
||||
$this->command->newLine();
|
||||
}
|
||||
|
||||
private function rollback(): void
|
||||
{
|
||||
// Remove only the test-seeded data (created recently)
|
||||
$cutoff = now()->subHour()->toDateTimeString();
|
||||
|
||||
// Delete call_translations first (FK constraint), then calls
|
||||
$callIds = DB::table('calls')
|
||||
->where('created_at', '>=', $cutoff)
|
||||
->pluck('id');
|
||||
|
||||
$translationsDeleted = DB::table('call_translations')
|
||||
->whereIn('call_id', $callIds)
|
||||
->delete();
|
||||
$this->command->info("Removed {$translationsDeleted} test call translations.");
|
||||
|
||||
$deleted = DB::table('calls')
|
||||
->where('created_at', '>=', $cutoff)
|
||||
->delete();
|
||||
$this->command->info("Removed {$deleted} test calls.");
|
||||
|
||||
$deleted = DB::table('taggable_taggables')
|
||||
->where('taggable_type', 'App\Models\User')
|
||||
->where('created_at', '>=', $cutoff)
|
||||
->delete();
|
||||
$this->command->info("Removed {$deleted} test tag assignments.");
|
||||
|
||||
$this->command->info('Re-indexing affected users in Elasticsearch (synchronously)...');
|
||||
$this->reindexAffectedUsers();
|
||||
$this->command->info('Rollback complete.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user