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();
Including the primary key in search
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);
Performing a search
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.
