TNTSearch 轻量级全文索引+中文分词
选用 TNTSearch 的原因:轻,方便移植,不需要额外安装服务,能减少后期维护的工作量。搜索的效果也还不错,可以满足大多数项目场景,如果对性能和精准度要求较高,还是使用 Elasticsearch 吧。因TNTSearch使用的逗号空格分词,所以我们还需要一个中文分词的服务。
这里我选用的是 fukuball/jieba-php 选它的原因也是轻量,也不需要过多的依赖,部署方便。
TNTSearch 集成教程
https://laravel-china.org/articles/3702/full-text-indexing-engine-implemented-in-tntsearch-php
教程讲的很清楚,也没有什么坑,根据教程一步步来就可以了。这里就不在重复了。
下面主要说说 TNTSearch 怎么集成 fukuball/jieba-php 中文分词。
安装 fukuball/jieba-php
composer composer require fukuball/jieba-php:dev-master
注:fukuball/jieba-php 分词对内存有要求,如果内存过小,分词的时候可能会报错。
开始集成
-
修改配置 app/config/scout.php 增加 jieba 的配置项
'tntsearch' => [ ... 'tokenizer' => [ ... 'jieba' => [ 'dict' => 'small', ], .... ], ... ],
-
新建一个 Tokenizer
app/Handlers/TokenizerHandler.php<?php namespace App\Handlers; use Fukuball\Jieba\Jieba; use Fukuball\Jieba\Finalseg; use TeamTNT\TNTSearch\Support\TokenizerInterface; class TokenizerHandler implements TokenizerInterface { public function __construct(array $options = []) { Jieba::init($options); Finalseg::init($options); } public function tokenize($text, $stopwords = []) { return is_numeric($text) ? [] : $this->getTokens($text, $stopwords); } public function getTokens($text, $stopwords = []) { $split = Jieba::cutForSearch($text); return $split; } }
-
新建服务提供者,用来取代 laravel-scout-tntsearch-driver 默认的服务提供者
app/Providers/ScoutServiceProvider.php<?php namespace App\Providers; use TeamTNT\TNTSearch\TNTSearch; use Laravel\Scout\EngineManager; use TeamTNT\Scout\Console\ImportCommand; use TeamTNT\Scout\Engines\TNTSearchEngine; use TeamTNT\Scout\TNTSearchScoutServiceProvider; use App\Handlers\TokenizerHandler; class ScoutServiceProvider extends TNTSearchScoutServiceProvider { public function boot() { $this->app[EngineManager::class]->extend('tntsearch', function ($app) { $tnt = new TNTSearch(); $driver = config('database.default'); $config = config('scout.tntsearch') + config("database.connections.{$driver}"); $tnt->loadConfig($config); # 注入中文分词服务 $tnt->setTokenizer(new TokenizerHandler(config('scout.tntsearch.tokenizer.jieba'))); $tnt->setDatabaseHandle(app('db')->connection()->getPdo()); $this->setFuzziness($tnt); $this->setAsYouType($tnt); return new TNTSearchEngine($tnt); }); if ($this->app->runningInConsole()) { $this->commands([ ImportCommand::class, ]); } } }
- 注册服务提供者,将 TNTSearchScoutServiceProvider 取消注册
app/config/app.php... 'providers' => [ ... SocialiteProviders\Manager\ServiceProvider::class, # TeamTNT\Scout\TNTSearchScoutServiceProvider::class, ... ] ...
至此集成完毕,可以去测试一下效果。
当然也可以根据 laravel-scout-tntsearch-driver 源码修改,然后打包成一个自己包,只是这样以后就失去了原包的升级服务。可以自行取舍,没有对错,适合就好。
如果有问题可以一起探讨一下。
我开源的 laraCMS 已集成了 TNTSearch ,如果有兴趣可以去github查看源码,也可以去在线体验
Github: https://github.com/wanglelecc/laracms
预览:https://www.56br.com/