Просмотр файла app/Console/Commands/SearchImport.php

Размер файла: 3.17Kb
<?php

namespace App\Console\Commands;

use App\Models\Article;
use App\Models\Comment;
use App\Models\Down;
use App\Models\Guestbook;
use App\Models\Item;
use App\Models\News;
use App\Models\Offer;
use App\Models\Photo;
use App\Models\Post;
use App\Models\Topic;
use App\Models\User;
use App\Models\Vote;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
use Symfony\Component\Console\Command\Command as SymfonyCommand;

class SearchImport extends Command
{
    protected $signature = 'search:import';
    protected $description = 'Sync existing records to search index';

    /**
     * Handle
     */
    public function handle(): int
    {
        $models = [
            Article::class,
            Comment::class,
            Down::class,
            Guestbook::class,
            Item::class,
            News::class,
            Offer::class,
            Photo::class,
            Post::class,
            Topic::class,
            User::class,
            Vote::class,
        ];

        DB::disableQueryLog();
        DB::connection()->unsetEventDispatcher();
        DB::table('search')->truncate();

        foreach ($models as $modelClass) {
            $this->syncModelRecords($modelClass);
        }

        $this->info('Search index sync completed!');

        return SymfonyCommand::SUCCESS;
    }

    /**
     * SyncModelRecords
     */
    protected function syncModelRecords(string $modelClass): void
    {
        $this->line(PHP_EOL . "Processing model: {$modelClass}");

        try {
            $model = new $modelClass();
            $searchableFields = $model->searchableFields();

            if (empty($searchableFields)) {
                $this->warn("Skipping {$modelClass} - no searchable fields defined");

                return;
            }

            $total = 0;
            $count = $model->count();

            $this->line("Found {$count} records to index");

            $progressBar = $this->output->createProgressBar($count);
            $progressBar->start();

            // Используем chunkById для стабильной пакетной обработки
            $model->chunkById(1000, function ($records) use ($progressBar, &$total) {
                $searchData = [];

                foreach ($records as $record) {
                    if (! $record->shouldBeSearchable()) {
                        continue;
                    }

                    $searchData[] = [
                        'text'        => $record->buildSearchText(),
                        'created_at'  => $record->created_at,
                        'relate_type' => $record->getMorphClass(),
                        'relate_id'   => $record->getKey(),
                    ];

                    $total++;
                    $progressBar->advance();
                }

                if ($searchData) {
                    DB::table('search')->insert($searchData);
                }
            });

            $progressBar->finish();
            $this->info(PHP_EOL . "Successfully indexed {$total} of {$count} records for {$modelClass}");
        } catch (\Exception $e) {
            $this->error("Error processing {$modelClass}: " . $e->getMessage());
        }
    }
}