Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Tntsearch Laravel Package

teamtnt/tntsearch

TNTSearch is a pure-PHP full-text search engine with fuzzy search, “search as you type”, geo-search, stemming, custom tokenizers, BM25 ranking, boolean queries, highlighting, and dynamic index updates—fast to integrate and deploy via Packagist.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup in Laravel
1. **Install the package**:
   ```bash
   composer require teamtnt/tntsearch
  1. Configure the connection in config/tntsearch.php (or publish it first):

    php artisan vendor:publish --provider="TeamTNT\TNTSearch\TNTSearchServiceProvider"
    

    Example config:

    'connections' => [
        'mysql' => [
            'driver'    => 'mysql',
            'host'      => env('DB_HOST'),
            'database'  => env('DB_DATABASE'),
            'username'  => env('DB_USERNAME'),
            'password'  => env('DB_PASSWORD'),
            'storage'   => storage_path('app/tntsearch'),
        ],
    ],
    
  2. First use case: Basic search

    use TeamTNT\TNTSearch\TNTSearch;
    
    $tnt = new TNTSearch;
    $tnt->loadConfig(config('tntsearch.connections.mysql'));
    
    // Create an index
    $indexer = $tnt->createIndex('articles.index');
    $indexer->query('SELECT id, title, content FROM articles');
    $indexer->run();
    
    // Search
    $results = $tnt->search('laravel full text search', 10);
    

Implementation Patterns

1. Indexing Workflows

  • Batch Indexing: Use createIndex() with a SQL query to index existing data.
    $indexer = $tnt->createIndex('products.index');
    $indexer->query('SELECT id, name, description FROM products WHERE active = 1');
    $indexer->run();
    
  • Dynamic Updates: Update indexes incrementally without reindexing.
    $index = $tnt->getIndex('articles.index');
    $index->insert(['id' => 123, 'title' => 'New Article', 'content' => '...']);
    $index->update(123, ['title' => 'Updated Title']);
    $index->delete(456);
    

2. Search Patterns

  • Boolean Search:
    $results = $tnt->searchBoolean('(laravel AND "full text") NOT tutorial');
    
  • Fuzzy Search (typos/tolerant queries):
    $tnt->fuzziness(true); // Enable fuzzy matching
    $results = $tnt->search('laravel', 5); // Matches "laravel", "laravell", etc.
    
  • Geo-Search (for location-based apps):
    $geoSearch = $tnt->geoSearch('restaurants.index');
    $nearby = $geoSearch->findNearest(
        ['latitude' => 40.7128, 'longitude' => -74.0060], // NYC
        5, // 5km radius
        10 // Top 10 results
    );
    

3. Integration with Laravel Scout

  • Use the laravel-scout-tntsearch-driver for seamless Scout integration:
    composer require teamtnt/laravel-scout-tntsearch-driver
    
    Configure in config/scout.php:
    'driver' => 'tntsearch',
    
    Now use Scout’s familiar API:
    $user->search('John Doe'); // Uses TNTSearch under the hood
    

4. Text Classification

  • Train a classifier for categorization:
    $classifier = new \TeamTNT\TNTSearch\Classifier\TNTClassifier();
    $classifier->learn('Laravel is awesome', 'framework');
    $classifier->learn('Symfony is great', 'framework');
    $guess = $classifier->predict('This uses PHP');
    // Returns: ['label' => 'framework', 'confidence' => 0.92]
    
    Save/load for reuse:
    $classifier->save(storage_path('app/sports.cls'));
    $loaded = new \TeamTNT\TNTSearch\Classifier\TNTClassifier();
    $loaded->load(storage_path('app/sports.cls'));
    

5. Customization

  • Tokenizers: Override tokenization logic (e.g., for hashtags or emojis):
    $tokenizer = new class extends \TeamTNT\TNTSearch\Tokenizer\AbstractTokenizer {
        protected static $pattern = '/[^\w#]+/'; // Include hashtags
    };
    $indexer->setTokenizer($tokenizer);
    
  • Stemmers: Add language support (e.g., German):
    $tnt->loadConfig(['stemmer' => \TeamTNT\TNTSearch\Stemmer\GermanStemmer::class]);
    

Gotchas and Tips

Pitfalls

  1. Storage Permissions:

    • Ensure the storage path in config is writable:
      chmod -R 775 storage_path('app/tntsearch')
      
    • Error: PDOException: unable to open database file → Fix permissions.
  2. Primary Key Assumptions:

    • TNTSearch defaults to id as the primary key. Override with:
      $indexer->setPrimaryKey('custom_id');
      
  3. Boolean Search Syntax:

    • Use double quotes for exact phrases: "full text".
    • Parentheses for grouping: (A AND B) OR C.
    • Prefix - for exclusion: laravel -tutorial.
  4. Fuzzy Search Limits:

    • High fuzzy_distance (e.g., >3) slows queries. Default is 2.
    • Disable with $tnt->fuzziness(false).
  5. Geo-Search Precision:

    • Latitude/longitude must be numeric (not strings).
    • Distance is in kilometers by default.
  6. Index Corruption:

    • If searches return empty results, reindex:
      $indexer->reindex();
      

Debugging Tips

  • Enable Logging:
    $tnt->setLogger(new \Monolog\Logger('tntsearch', [...]));
    
  • Check Index Status:
    $index = $tnt->getIndex('articles.index');
    var_dump($index->getStats()); // Shows indexed docs, words, etc.
    
  • SQL Query Debugging:
    • Wrap $indexer->query() in a transaction to test SQL:
      DB::transaction(function () use ($indexer) {
          $indexer->query('SELECT * FROM articles LIMIT 10')->run();
      });
      

Performance Optimization

  1. Selective Indexing:
    • Index only relevant columns:
      $indexer->query('SELECT id, title, content FROM articles');
      
  2. Limit Fuzzy Search:
    • Disable for high-volume searches:
      $tnt->fuzziness(false);
      
  3. Batch Updates:
    • Use insert() in bulk (e.g., via collect()):
      $newArticles = Article::where('updated_at', '>', now()->subHour())->get();
      $index->insert($newArticles->toArray());
      
  4. Cache Results:
    • Cache search results in Laravel’s cache:
      $cacheKey = "tntsearch:articles:{$query}";
      return Cache::remember($cacheKey, now()->addMinutes(5), function () use ($tnt, $query) {
          return $tnt->search($query, 20);
      });
      

Extension Points

  1. Custom Drivers:
    • Extend \TeamTNT\TNTSearch\Driver\AbstractDriver for new storage backends (e.g., PostgreSQL).
  2. Highlighting:
    • Use the highlight() method (v5.0+):
      $highlighted = $tnt->highlight('laravel', $results, ['title', 'content']);
      
  3. Plugins:
    • Hook into the TokenizerInterface or StemmerInterface for custom logic.
  4. Scout Events:
    • Listen to Scout events to trigger TNTSearch updates:
      Scout::searching(function ($model) {
          // Custom logic before search
      });
      

Laravel-Specific Quirks

  1. Service Provider:
    • Register the config publisher in AppServiceProvider:
      if (!class_exists(\TeamTNT\TNTSearch\TNTSearchServiceProvider::class)) {
          $this->mergeConfigFrom(__DIR__.'/../../../vendor/teamtnt/tntsearch/config/tntsearch.php', 'tntsearch');
      }
      
  2. Queue Jobs:
    • Offload indexing to queues:
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
yandex/translate-api
voku/simple_html_dom
league/flysystem-vfs
bkwld/upchuck
filament/spatie-laravel-tags-plugin
capell-app/block-library
axium/identity
cetria/laravel-dummy-models
cetria/reflection-helper
agropredict/sso-auth-bundle
evolvestudio/spam-protection
datacore/hub-sdk
develia/commons
cuci/prototurk-sdk
cuci/prototurk-sdk-symfony
develia/geo-bundle
dreamzy/livewire-charts
touchestate-sdk/php-sdk
22h/doctrine-garbage-collection-bundle
agtp/agtp-php