From d41d35be46ca8753875c158fa3d9ba7d928eb309 Mon Sep 17 00:00:00 2001 From: DariusIII Date: Thu, 1 Jan 2026 13:19:06 +0100 Subject: [PATCH] Update manticore index creation --- .../Commands/CreateManticoreIndexes.php | 13 ++ app/Console/Commands/CreateMediaIndexes.php | 11 ++ .../Search/Drivers/ManticoreSearchDriver.php | 141 ++++++++++++------ 3 files changed, 120 insertions(+), 45 deletions(-) diff --git a/app/Console/Commands/CreateManticoreIndexes.php b/app/Console/Commands/CreateManticoreIndexes.php index c73cec3f2..aa381f834 100644 --- a/app/Console/Commands/CreateManticoreIndexes.php +++ b/app/Console/Commands/CreateManticoreIndexes.php @@ -195,6 +195,19 @@ class CreateManticoreIndexes extends Command return true; } + // Check for data_dir configuration error + if (str_contains($e->getMessage(), 'data_dir')) { + $this->error("Failed to create {$indexName} index: ".$e->getMessage()); + $this->newLine(); + $this->warn('ManticoreSearch requires data_dir to be set in its configuration file.'); + $this->info('To fix this, edit your ManticoreSearch config file (usually /etc/manticoresearch/manticore.conf):'); + $this->line(' 1. Add or uncomment: data_dir = /var/lib/manticore'); + $this->line(' 2. Ensure the directory exists and is writable by the manticore user'); + $this->line(' 3. Restart ManticoreSearch: sudo systemctl restart manticore'); + + return false; + } + $this->error("Failed to create {$indexName} index: ".$e->getMessage()); return false; diff --git a/app/Console/Commands/CreateMediaIndexes.php b/app/Console/Commands/CreateMediaIndexes.php index f01aa1543..725a7d236 100644 --- a/app/Console/Commands/CreateMediaIndexes.php +++ b/app/Console/Commands/CreateMediaIndexes.php @@ -181,6 +181,17 @@ class CreateMediaIndexes extends Command $this->warn("Index {$indexName} already exists. Use --drop to recreate."); return true; } + // Check for data_dir configuration error + if (str_contains($e->getMessage(), 'data_dir')) { + $this->error("Failed to create index {$indexName}: " . $e->getMessage()); + $this->newLine(); + $this->warn('ManticoreSearch requires data_dir to be set in its configuration file.'); + $this->info('To fix this, edit your ManticoreSearch config file (usually /etc/manticoresearch/manticore.conf):'); + $this->line(' 1. Add or uncomment: data_dir = /var/lib/manticore'); + $this->line(' 2. Ensure the directory exists and is writable by the manticore user'); + $this->line(' 3. Restart ManticoreSearch: sudo systemctl restart manticore'); + return false; + } $this->error("Failed to create index {$indexName}: " . $e->getMessage()); return false; } catch (\Throwable $e) { diff --git a/app/Services/Search/Drivers/ManticoreSearchDriver.php b/app/Services/Search/Drivers/ManticoreSearchDriver.php index dd0cf643a..72a210d15 100644 --- a/app/Services/Search/Drivers/ManticoreSearchDriver.php +++ b/app/Services/Search/Drivers/ManticoreSearchDriver.php @@ -486,58 +486,97 @@ class ManticoreSearchDriver implements SearchDriverInterface private function createIndexIfNotExists(string $index): void { try { + // Use the tables() API which properly handles settings + $indices = $this->manticoreSearch->tables(); + if ($index === 'releases_rt') { - $this->manticoreSearch->table($index)->create([ - 'name' => ['type' => 'text'], - 'searchname' => ['type' => 'text'], - 'fromname' => ['type' => 'text'], - 'filename' => ['type' => 'text'], - 'categories_id' => ['type' => 'integer'], - // External media IDs for efficient searching - 'imdbid' => ['type' => 'integer'], - 'tmdbid' => ['type' => 'integer'], - 'traktid' => ['type' => 'integer'], - 'tvdb' => ['type' => 'integer'], - 'tvmaze' => ['type' => 'integer'], - 'tvrage' => ['type' => 'integer'], - 'videos_id' => ['type' => 'integer'], - 'movieinfo_id' => ['type' => 'integer'], + $indices->create([ + 'index' => $index, + 'body' => [ + 'settings' => [ + 'min_prefix_len' => 0, + 'min_infix_len' => 2, + ], + 'columns' => [ + 'name' => ['type' => 'text'], + 'searchname' => ['type' => 'text'], + 'fromname' => ['type' => 'text'], + 'filename' => ['type' => 'text'], + 'categories_id' => ['type' => 'integer'], + // External media IDs for efficient searching + 'imdbid' => ['type' => 'integer'], + 'tmdbid' => ['type' => 'integer'], + 'traktid' => ['type' => 'integer'], + 'tvdb' => ['type' => 'integer'], + 'tvmaze' => ['type' => 'integer'], + 'tvrage' => ['type' => 'integer'], + 'videos_id' => ['type' => 'integer'], + 'movieinfo_id' => ['type' => 'integer'], + ], + ], ]); - cli()->info('Created releases_rt index with external ID fields'); + cli()->info('Created releases_rt index with external ID fields and infix search support'); } elseif ($index === 'predb_rt') { - $this->manticoreSearch->table($index)->create([ - 'title' => ['type' => 'text'], - 'filename' => ['type' => 'text'], - 'source' => ['type' => 'text'], + $indices->create([ + 'index' => $index, + 'body' => [ + 'settings' => [ + 'min_prefix_len' => 0, + 'min_infix_len' => 2, + ], + 'columns' => [ + 'title' => ['type' => 'text'], + 'filename' => ['type' => 'text'], + 'source' => ['type' => 'text'], + ], + ], ]); - cli()->info('Created predb_rt index'); + cli()->info('Created predb_rt index with infix search support'); } elseif ($index === 'movies_rt') { - $this->manticoreSearch->table($index)->create([ - 'imdbid' => ['type' => 'integer'], - 'tmdbid' => ['type' => 'integer'], - 'traktid' => ['type' => 'integer'], - 'title' => ['type' => 'text'], - 'year' => ['type' => 'text'], - 'genre' => ['type' => 'text'], - 'actors' => ['type' => 'text'], - 'director' => ['type' => 'text'], - 'rating' => ['type' => 'text'], - 'plot' => ['type' => 'text'], + $indices->create([ + 'index' => $index, + 'body' => [ + 'settings' => [ + 'min_prefix_len' => 0, + 'min_infix_len' => 2, + ], + 'columns' => [ + 'imdbid' => ['type' => 'integer'], + 'tmdbid' => ['type' => 'integer'], + 'traktid' => ['type' => 'integer'], + 'title' => ['type' => 'text'], + 'year' => ['type' => 'text'], + 'genre' => ['type' => 'text'], + 'actors' => ['type' => 'text'], + 'director' => ['type' => 'text'], + 'rating' => ['type' => 'text'], + 'plot' => ['type' => 'text'], + ], + ], ]); - cli()->info('Created movies_rt index'); + cli()->info('Created movies_rt index with infix search support'); } elseif ($index === 'tvshows_rt') { - $this->manticoreSearch->table($index)->create([ - 'title' => ['type' => 'text'], - 'tvdb' => ['type' => 'integer'], - 'trakt' => ['type' => 'integer'], - 'tvmaze' => ['type' => 'integer'], - 'tvrage' => ['type' => 'integer'], - 'imdb' => ['type' => 'integer'], - 'tmdb' => ['type' => 'integer'], - 'started' => ['type' => 'text'], - 'type' => ['type' => 'integer'], + $indices->create([ + 'index' => $index, + 'body' => [ + 'settings' => [ + 'min_prefix_len' => 0, + 'min_infix_len' => 2, + ], + 'columns' => [ + 'title' => ['type' => 'text'], + 'tvdb' => ['type' => 'integer'], + 'trakt' => ['type' => 'integer'], + 'tvmaze' => ['type' => 'integer'], + 'tvrage' => ['type' => 'integer'], + 'imdb' => ['type' => 'integer'], + 'tmdb' => ['type' => 'integer'], + 'started' => ['type' => 'text'], + 'type' => ['type' => 'integer'], + ], + ], ]); - cli()->info('Created tvshows_rt index'); + cli()->info('Created tvshows_rt index with infix search support'); } } catch (\Throwable $e) { cli()->error('Error creating index '.$index.': '.$e->getMessage()); @@ -769,7 +808,19 @@ class ManticoreSearchDriver implements SearchDriverInterface $results = $query->get(); } catch (ResponseException $e) { - Log::error('ManticoreSearch fuzzySearchIndexes ResponseException: '.$e->getMessage(), [ + $message = $e->getMessage(); + + // Check if fuzzy search failed due to missing min_infix_len + // This happens when index was created without proper settings + if (str_contains($message, 'min_infix_len')) { + Log::warning('ManticoreSearch fuzzySearchIndexes: Fuzzy search unavailable - index missing min_infix_len setting. Please recreate the index with: php artisan nntmux:manticore-create --drop', [ + 'index' => $index, + ]); + // Fall back to regular search without fuzzy + return $this->searchIndexes($index, '', [], $searchArray); + } + + Log::error('ManticoreSearch fuzzySearchIndexes ResponseException: '.$message, [ 'index' => $index, 'searchArray' => $searchArray, ]);