rf1705/tntsearch

一个功能齐全的PHP全文搜索引擎

资助包维护!
teamtnt


README

Latest Version on Packagist Total Downloads Software License Build Status Slack Status

TNTSearch

TNTSearch

TNTSearch是一个完全用PHP编写的全文搜索引擎(FTS)。简单的配置允许您在几分钟内添加令人惊叹的搜索体验。功能包括

  • 模糊搜索
  • 边打字边搜索
  • 地理搜索
  • 文本分类
  • 词干提取
  • 自定义分词器
  • Bm25排名算法
  • 布尔搜索
  • 结果高亮显示
  • 动态索引更新(无需每次都重新索引)
  • 通过Packagist.org轻松部署

我们还创建了一些演示页面,展示了使用n-gram的容错检索。该包包含一些辅助函数,如Jaro-Winkler和余弦相似度,用于距离计算。它支持英语、克罗地亚语、阿拉伯语、意大利语、俄语、葡萄牙语和乌克兰语的词干提取。如果内置的词干提取器不足,该引擎允许您轻松地插件任何兼容的snowball词干提取器。该包的一些分支甚至支持中文。请为其他语言做出贡献!

与许多其他引擎不同,索引可以很容易地更新,而无需重新索引或使用delta。

查看 在线演示  |  关注我们Twitter,或 Facebook  |  访问我们的赞助商

演示

教程

高级产品

如果您正在使用TNT Search并发现它很有用,请查看我们的高级分析工具

在Open Collective上支持我们

安装

安装TNTSearch最简单的方法是通过 composer

composer require teamtnt/tntsearch

要求

在您继续之前,请确保您的服务器满足以下要求

  • PHP >= 7.1
  • PDO PHP扩展
  • SQLite PHP扩展
  • mbstring PHP扩展

示例

创建索引

为了能够执行全文搜索查询,您必须创建一个索引。

用法

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//optional
]);

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

重要:"storage" 设置标记了所有索引将保存的文件夹,请确保您有写入此文件夹的权限,否则您可能会遇到以下异常抛出

  • [PDOException] SQLSTATE[HY000] [14] 无法打开数据库文件 *

注意:如果您的主键不同于 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); //returns an array of 12 document ids that best match your query

// to display the results you need an additional query against your application database
// 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");

//this will return all documents that have romeo in it but not juliet
$res = $tnt->searchBoolean("romeo -juliet");

//returns all documents that have romeo or hamlet in it
$res = $tnt->searchBoolean("romeo or hamlet");

//returns all documents that have either romeo AND juliet or 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; //represents the Levenshtein distance;
use TeamTNT\TNTSearch\TNTSearch;

$tnt = new TNTSearch;

$tnt->loadConfig($config);
$tnt->selectIndex("name.index");
$tnt->fuzziness = true;

//when the fuzziness flag is set to true, the keyword juleit will return
//documents that match the word juliet, the default Levenshtein distance is 2
$res = $tnt->search("juleit");

更新索引

创建索引后,您无需在更改文档集合时每次都重新索引。TNTSearch支持动态索引更新。

use TeamTNT\TNTSearch\TNTSearch;

$tnt = new TNTSearch;

$tnt->loadConfig($config);
$tnt->selectIndex("name.index");

$index = $tnt->getIndex();

//to insert a new document to the index
$index->insert(['id' => '11', 'title' => 'new title', 'article' => 'new article']);

//to update an existing document
$index->update(11, ['id' => '11', 'title' => 'updated title', 'article' => 'updated article']);

//to delete the document from index
$index->delete(12);

自定义分词器

首先,创建您自己的Tokenizer类。它应该扩展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//optional,
    '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; //km

$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']); //returns "Not sports"

保存分类器

$classifier->save('sports.cls');

加载分类器

$classifier = new TNTClassifier();
$classifier->load('sports.cls');

驱动器

PS4Ware

您可以使用这个包,但如果它进入您的生产环境,我们非常希望您发送我们一款您选择的PS4游戏。这样,您支持我们进一步开发和添加新功能。

我们的地址是:TNT Studio,Sv. Mateja 19,10010 扎格雷布,克罗地亚。

我们将在这里发布所有收到的游戏 这里

支持 OpenCollective OpenCollective

Buy Me a Coffee at ko-fi.com

赞助者

通过每月捐赠支持我们,帮助我们继续我们的活动。[成为赞助者]

赞助商

成为赞助商,并将您的标志放在我们的GitHub README上,链接到您的网站。[成为赞助商]

致谢

许可协议

MIT许可协议(MIT)。有关更多信息,请参阅许可文件

由克罗地亚的TNT Studio(@tntstudiohr博客)用♥制作