Searching

Basic search

TNTSearch provides a straightforward API for creating indexes and performing full-text searches. This guide covers the core workflow: indexing your data, running searches, and working with results.


Creating an index

Before you can search, you need to create an index from your data source. An index is built by running a SQL query against your database and processing the results.

use TeamTNT\TNTSearch\TNTSearch;

$tnt = new TNTSearch;

$tnt->loadConfig([
    'driver'   => 'mysql',
    'host'     => 'localhost',
    'database' => 'dbname',
    'username' => 'user',
    'password' => 'pass',
    'storage'  => '/path/to/indexes/',
    'stemmer'  => \TeamTNT\TNTSearch\Stemmer\PorterStemmer::class,
]);

$indexer = $tnt->createIndex('articles.index');
$indexer->query('SELECT id, title, body FROM articles;');
$indexer->run();

The first column in your SELECT should be the primary key. All other columns will be indexed for full-text search.

Custom primary key

If your primary key is not named id, specify it explicitly:

$indexer = $tnt->createIndex('posts.index');
$indexer->setPrimaryKey('post_id');
$indexer->query('SELECT post_id, title, content FROM posts;');
$indexer->run();

By default, the primary key column is not indexed as searchable text. If you want to be able to search by ID values:

$indexer = $tnt->createIndex('articles.index');
$indexer->query('SELECT id, title, body FROM articles;');
$indexer->includePrimaryKey();
$indexer->run();

Setting a language

You can set a language to automatically configure the right stemmer:

$indexer = $tnt->createIndex('articles.index');
$indexer->query('SELECT id, title, body FROM articles;');
$indexer->setLanguage('german');
$indexer->run();

Supported languages: arabic, croatian, french, german, italian, latvian, polish, porter (English), portuguese, russian, ukrainian.

Disabling output

During indexing, TNTSearch prints progress to stdout. To suppress this:

$indexer->disableOutput(true);

Once an index exists, searching is simple:

$tnt = new TNTSearch;
$tnt->loadConfig($config);
$tnt->selectIndex('articles.index');

$results = $tnt->search('romeo juliet', 12);

The second argument limits the number of results returned (default: 100).

Understanding results

The search() method returns an array with the following structure:

[
    'ids'            => [9, 7, 5, 6, 8, 10],  // document IDs ranked by relevance
    'hits'           => 6,                      // total number of matching documents
    'docScores'      => [9 => 3.45, ...],       // BM25 scores per document
    'execution_time' => '0.342 ms'              // search execution time
]

Results are ranked using the BM25 algorithm, which considers term frequency, inverse document frequency, and document length to produce relevance scores.

You should know!

TNTSearch returns document IDs, not full database records. You need to fetch the actual data from your database:

$ids = implode(',', $results['ids']);
$articles = DB::select("SELECT * FROM articles WHERE id IN ($ids) ORDER BY FIELD(id, $ids)");

Multi-word queries

When you search for multiple words, TNTSearch finds documents containing any of the words and ranks documents higher when they contain more of your search terms.

// Finds documents containing "romeo", "juliet", or both
// Documents with both words score higher
$results = $tnt->search('romeo juliet');

For strict boolean logic (requiring all words or specific combinations), see the Boolean search guide.


Search with stemming

When a stemmer is configured, searches automatically account for word variations. For example, with the PorterStemmer, a search for "swimming" will also match "swim", "swimmer", and "swam".

The stemmer is set during index creation and is automatically applied during search:

// At index time
$tnt->loadConfig([
    'stemmer' => \TeamTNT\TNTSearch\Stemmer\PorterStemmer::class,
    // ...
]);
$indexer = $tnt->createIndex('articles.index');
$indexer->query('SELECT id, title, body FROM articles;');
$indexer->run();

// At search time - stemmer is automatically loaded from the index
$tnt->selectIndex('articles.index');
$results = $tnt->search('swimming'); // also matches "swim", "swimmer", etc.
Previous
Tokenization