teamtnt/tntsearch

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

资助包维护!
teamtnt

安装次数: 2,198,454

依赖项: 28

建议者: 6

安全性: 0

星标: 3,069

关注者: 96

分支: 293

开放问题: 85

v4.3.0 2024-08-09 06:32 UTC

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 词干提取器。该包的一些分支甚至支持中文。请继续贡献其他语言!

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

查看 在线演示  |  关注我们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);

自定义分词器

首先,创建您自己的分词器类。它应该继承自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博客)以♥制作