概述
TNTSearch是一款完全用PHP編寫的全文搜索(FTS)引擎。只需簡單配置,你就能在幾分鐘內添加出色的搜索體驗。
功能包括
我們還創建了一些演示頁面,展示了n - gram在容錯檢索中的實際應用。該軟件包有許多輔助函數,如用于距離計算的Jaro - Winkler和余弦相似度函數。它支持英語、克羅地亞語、阿拉伯語、意大利語、俄語、葡萄牙語和烏克蘭語的詞干提取。如果內置的詞干提取器不夠用,該引擎允許你輕松插入任何兼容的Snowball詞干提取器。該軟件包的一些分支甚至支持中文。歡迎大家貢獻對其他語言的支持!
與許多其他引擎不同,TNTSearch的索引可以輕松更新,無需重新索引或使用增量更新。DigitalOcean
安裝
安裝TNTSearch最簡單的方法是通過composer:
composer require teamtnt/tntsearch
要求
在繼續之前,請確保你的服務器滿足以下要求:
示例
創建索引
為了能夠進行全文搜索查詢,你必須創建一個索引。 用法:
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'dbname',
'username' => 'user',
'password' => 'pass',
'storage' => '/var/www/tntsearch/examples/',
'stemmer' => \TeamTNT\TNTSearch\Stemmer\PorterStemmer::class//可選
]);
$indexer = $tnt->createIndex('name.index');
$indexer->query('SELECT id, article FROM articles;');
//$indexer->setLanguage('german'); $indexer->run();
重要提示:“storage”設置標記了所有索引將保存的文件夾,因此請確保對該文件夾有寫入權限,否則可能會拋出以下異常:[PDOException] SQLSTATE[HY000] [14] unable to open database file *
注意:如果你的主鍵不是id
,請按如下方式設置:
$indexer->setPrimaryKey('article_id');
使主鍵可搜索
默認情況下,主鍵是不可搜索的。如果你想讓主鍵可搜索,只需運行:
$indexer->includePrimaryKey();
搜索
搜索短語或關鍵詞非常簡單:
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig($config);
$tnt->selectIndex("name.index");
$res = $tnt->search("This is a test search", 12);
print_r($res); //返回一個包含12個與查詢最匹配的文檔ID的數組
// 要顯示結果,你需要針對應用程序數據庫進行額外查詢
// SELECT * FROM articles WHERE id IN $res ORDER BY FIELD(id, $res);
ORDER BY FIELD
子句很重要,否則數據庫引擎將無法按要求的順序返回結果。
布爾搜索
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig($config);
$tnt->selectIndex("name.index");
// 這將返回所有包含romeo但不包含juliet的文檔
$res = $tnt->searchBoolean("romeo -juliet");
// 返回所有包含romeo或hamlet的文檔
$res = $tnt->searchBoolean("romeo or hamlet");
// 返回所有包含romeo AND juliet或者prince AND hamlet的文檔
$res = $tnt->searchBoolean("(romeo juliet) or (prince hamlet)");
模糊搜索
可以通過設置以下成員變量來調整模糊度:
public $fuzzy_prefix_length = 2;
public $fuzzy_max_expansions = 50;
public $fuzzy_distance = 2; //代表萊文斯坦距離;
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig($config);
$tnt->selectIndex("name.index");
$tnt->fuzziness(true);
// 當模糊度標志設置為true時,關鍵詞juleit將返回與單詞juliet匹配的文檔,默認萊文斯坦距離為2
$res = $tnt->search("juleit");
更新索引
創建索引后,每次對文檔集合進行更改時,無需重新索引。TNTSearch支持動態索引更新。
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig($config);
$tnt->selectIndex("name.index");
$index = $tnt->getIndex();
// 向索引中插入新文檔
$index->insert(['id' => '11', 'title' => 'new title', 'article' => 'new article']);
// 更新現有文檔
$index->update(11, ['id' => '11', 'title' => 'updated title', 'article' => 'updated article']);
// 從索引中刪除文檔
$index->delete(12);
自定義分詞器
首先,創建你自己的分詞器類。它應該擴展AbstractTokenizer
類,定義單詞分割的$pattern
值,并且必須實現TokenizerInterface
接口:
use TeamTNT\TNTSearch\Support\AbstractTokenizer;
use TeamTNT\TNTSearch\Support\TokenizerInterface;
class SomeTokenizer extends AbstractTokenizer implements TokenizerInterface
{
static protected $pattern = '/[\s,\.]+/';
public function tokenize($text) {
return preg_split($this->getPattern(), strtolower($text), -1, PREG_SPLIT_NO_EMPTY);
}
}
這個分詞器將使用空格、逗號和句號來分割單詞。準備好分詞器后,你應該通過setTokenizer
方法將其傳遞給TNTIndexer
。
$someTokenizer = new SomeTokenizer;
$indexer = new TNTIndexer;
$indexer->setTokenizer($someTokenizer);
另一種方法是通過配置傳遞分詞器:
use TeamTNT\TNTSearch\TNTSearch;
$tnt = new TNTSearch;
$tnt->loadConfig([
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'dbname',
'username' => 'user',
'password' => 'pass',
'storage' => '/var/www/tntsearch/examples/',
'stemmer' => \TeamTNT\TNTSearch\Stemmer\PorterStemmer::class//可選,
'tokenizer' => \TeamTNT\TNTSearch\Support\SomeTokenizer::class
]);
$indexer = $tnt->createIndex('name.index');
$indexer->query('SELECT id, article FROM articles;');
$indexer->run();
地理搜索
索引
$candyShopIndexer = new TNTGeoIndexer;
$candyShopIndexer->loadConfig($config);
$candyShopIndexer->createIndex('candyShops.index');
$candyShopIndexer->query('SELECT id, longitude, latitude FROM candy_shops;');
$candyShopIndexer->run();
搜索
$currentLocation = [
'longitude' => 11.576124,
'latitude' => 48.137154
];
$distance = 2; //千米
$candyShopIndex = new TNTGeoSearch();
$candyShopIndex->loadConfig($config);
$candyShopIndex->selectIndex('candyShops.index');
$candyShops = $candyShopIndex->findNearest($currentLocation, $distance, 10);
分類
use TeamTNT\TNTSearch\Classifier\TNTClassifier;
$classifier = new TNTClassifier();
$classifier->learn("A great game", "Sports");
$classifier->learn("The election was over", "Not sports");
$classifier->learn("Very clean match", "Sports");
$classifier->learn("A clean but forgettable game", "Sports");
$guess = $classifier->predict("It was a close election");
var_dump($guess['label']); //返回 "Not sports"
保存分類器
$classifier->save('sports.cls');
加載分類器
$classifier = new TNTClassifier();
$classifier->load('sports.cls');
閱讀原文:原文鏈接
該文章在 2025/4/3 18:32:49 編輯過