laravel下TNTSearch+jieba-php实现中文全文搜索

上篇文章我们简单介绍了全文搜索的方案;
全文搜索和中文分词
TNTSearch+jieba-php这套组合可以在不依赖第三方的情况下实现中文全文搜索;
特别的适合博客这种小项目;
我新建一个项目用于演示;

laravel new tntsearch

创建一个文章表和文章模型;

php artisan make:model Models/Article -m

添加文章标题和内容字段
/database/migrations/2018_05_27_020900_create_articles_table.php

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title')->default('')->comment('标题');
            $table->mediumText('content')->comment('文章内容');
            $table->timestamps();
        });
    }

修改 .env 数据库配置项;

DB_DATABASE=homestead
DB_USERNAME=homestead
DB_PASSWORD=secret

运行迁移生成表;

php artisan migrate

创建填充文件;

php artisan make:seed ArticlesTableSeeder

生成测试数据;

    public function run()
    {
        DB::table('articles')->insert([
            [
                'title' => 'TNTSearch',
                'content' => '一个用PHP编写的功能齐全的全文搜索引擎'
            ],
            [
                'title' => 'jieba-php',
                'content' => '"结巴"中文分词:做最好的php中文分词、中文断词组件'
            ]
        ]);
    }

运行填充;

php artisan db:seed --class=ArticlesTableSeeder

/routes/web.php

<?php
use App\Models\Article;

Route::get('search', function () {
    // 为查看方便都转成数组
    dump(Article::all()->toArray());
});


准备工作终于做完了;
另外因为依赖 SQLite 存储索引;
再确认下自己的 php 开启了以下扩展;

pdo_sqlite
sqlite3
mbstring

现在开始正题;

以前;
我们需要自己 require scout;
scout 是 laravel 官方提供的用于全文搜索的扩展包;
它为我们提供了方便的命令行;
而且当我们增删改查文章后它会自动同步索引;
然后 require tntsearch 为 scout 提供的 laravel-scout-tntsearch-driver ;
再然后编写使用中文分词的逻辑;
现在有了 vanry 为我们造的轮子 laravel-scout-tntsearch ;
以前到现在这中间的步骤就可以省略了;
直接 require laravel-scout-tntsearch-driver ;

composer require vanry/laravel-scout-tntsearch

添加 Provider ;
config/app.php

    'providers' => [

        // ...

        /**
         * TNTSearch 全文搜索
         */
        Laravel\Scout\ScoutServiceProvider::class,
        Vanry\Scout\TNTSearchScoutServiceProvider::class,
    ],

中文分词 require jieba-php

composer require fukuball/jieba-php

发布配置项;

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

配置项中增加 tntsearch ;
/config/scout.php ;

'tntsearch' => [
    'storage' => storage_path('indexes'), //必须有可写权限
    'fuzziness' => env('TNTSEARCH_FUZZINESS', false),
    'searchBoolean' => env('TNTSEARCH_BOOLEAN', false),
    'asYouType' => false,

    'fuzzy' => [
        'prefix_length' => 2,
        'max_expansions' => 50,
        'distance' => 2,
    ],

    'tokenizer' => [
        'driver' => env('TNTSEARCH_TOKENIZER', 'default'),

        'jieba' => [
            'dict' => 'small',
            //'user_dict' => resource_path('dicts/mydict.txt'), //自定义词典路径
        ],

        'analysis' => [
            'result_type' => 2,
            'unit_word' => true,
            'differ_max' => true,
        ],

        'scws' => [
            'charset' => 'utf-8',
            'dict' => '/usr/local/scws/etc/dict.utf8.xdb',
            'rule' => '/usr/local/scws/etc/rules.utf8.ini',
            'multi' => 1,
            'ignore' => true,
            'duality' => false,
        ],
    ],

    'stopwords' => [
        '的',
        '了',
        '而是',
    ],
],

增加配置项;
/.env ;

SCOUT_DRIVER=tntsearch
TNTSEARCH_TOKENIZER=jieba

模型中定义全文搜索;
/app/Models/Article.php

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;

class Article extends Model
{
    use Searchable;

    /**
     * 索引的字段
     *
     * @return array
     */
    public function toSearchableArray()
    {
        return $this->only('id', 'title', 'content');
    }
}

php 默认的 memory_limit 是 128M;
为了防止 PHP Fatal error: Allowed memory size of n bytes exhausted ;
咱给增加到 256M 以解决内存不够报错的问题;
/app/Providers/AppServiceProvider.php

    public function boot()
    {
        /**
         * 增加内存防止中文分词报错
         */
        ini_set('memory_limit', "256M");
    }

生成索引;

php artisan scout:import "App\Models\Article"

使用起来也相当简单;
只需要把要搜索的内容传给 search() 方法即可;
/routes/web.php

<?php
use App\Models\Article;

Route::get('search', function () {
    // 为查看方便都转成数组
    dump(Article::all()->toArray());
    dump(Article::search('功能齐全的搜索引擎')->get()->toArray());
});


成功的查出了数据;

最后我们再测下修改数据后的同步索引;
/routes/web.php

<?php
use App\Models\Article;

Route::get('search', function () {
    // 为查看方便都转成数组
    dump(Article::all()->toArray());
    dump('下面搜索的是:功能齐全的搜索引擎');
    dump(Article::search('功能齐全的搜索引擎')->get()->toArray());
    dump('此处把content改为:让全文检索变的简单而强大');
    // 修改 content 测试索引是否会自动同步
    $first = Article::find(1);
    $first->content = '让全文检索变的简单而强大';
    $first->save();
    dump('下面搜索的是:功能齐全的搜索引擎');
    dump(Article::search('功能齐全的搜索引擎')->get()->toArray());
    dump('下面搜索的是:简单的检索');
    dump(Article::search('简单的检索')->get()->toArray());
});

白俊遥博客
请先登录后发表评论
  • latest comments
  • 总共58条评论
白俊遥博客

哄着自己玩 :一切照做,但好像没有成功分词,因为搜不出来,好比这段“一个用PHP编写的功能齐全的全文搜索引擎” 搜索“功能齐全的搜索引擎”搜不到,输入全文能搜到。安装的扩展包 "require": { "php": "^7.3|^8.0", "encore/laravel-admin": "1.*", "fideloper/proxy": "^4.4", "fruitcake/laravel-cors": "^2.0", "fukuball/jieba-php": "^0.33.0", "guzzlehttp/guzzle": "^7.0.1", "ichynul/iframe-tabs": "^1.3", "laravel/framework": "^8.12", "laravel/scout": "^8.6", "laravel/tinker": "^2.5", "tymon/jwt-auth": "^1.0", "vanry/laravel-scout-tntsearch": "^2.3" },

2021-03-23 22:33:51 回复

白俊遥博客

hcweb :laravel8安装失败

2020-10-19 10:01:05 回复

白俊遥博客

明月清风 :大佬我的操作步骤没有遇到问题,问题是我分词查询的结果还是有两条记录同时出现 和搜索全部是一个结果

2020-06-22 16:03:15 回复

白俊遥博客

bentai :composer require vanry/laravel-scout-tntsearch报错  是版本问题吗Your requirements could not be resolved to an installable set of packages.

2019-12-10 14:07:51 回复

白俊遥博客

hcweb :我也遇到 朋友处理了吗

2020-10-19 15:56:50 回复

白俊遥博客

@揪 :生成索引的时候 报错 Call to undefined method Illuminate\Database\Query\Builder::only()  

2018-12-26 11:27:20 回复

白俊遥博客

:为什么最多只能查出501条记录?? 这个怎么解决?还有 search 后面只能跟简单的where  其他的限定,比如whereIn 这些就报错了。大神  有什么解决办法?

2018-11-06 14:29:00 回复

白俊遥博客

xiaopeng829 :我问一下大佬,我自己新增的数据为什么查不到呢,我就是copy了一下你给的示例的两条数据,换了一下content里面的内容,输入关键词就查不到,为什么呢?

2018-10-30 16:56:03 回复

白俊遥博客 白俊遥博客

云淡风晴 :清除缓存;重新生成索引试试?

2018-10-30 20:48:57 回复

白俊遥博客

xiaopeng829 :不行呀,亲

2018-10-31 09:40:58 回复

白俊遥博客

手持面包跳舞

2018-12-16 14:54:12 回复

白俊遥博客

小六HI :php artisan scout:import "App\Models\Article"问题1:需要写成定时任务来执行吗?有没有好办法更新提交文章后的索引?问题2:打开这个测试地址执行的很慢,需要11-12s 才有结果,是 win 环境问题还是?

2018-09-20 15:15:14 回复

白俊遥博客 白俊遥博客

云淡风晴 :1. 在增删改文章后会自动更新缓存;  2. 可能跟环境有关;追求速度可以试试 https://baijunyao.com/article/156

2018-10-20 22:00:39 回复

白俊遥博客

xiaopeng829 :在吗

2018-10-30 17:00:00 回复

白俊遥博客

小六HI :在了。。

2018-10-31 11:18:44 回复

白俊遥博客

小六HI :感谢提示,看看你的博客操作去了;Linux 下查询速度好多了。

2018-10-31 11:20:07 回复

白俊遥博客

xiaopeng829 :这个分词你都整完了吗?

2018-10-31 11:54:28 回复

白俊遥博客

手持面包跳舞 白俊遥博客

2018-12-16 14:52:53 回复

白俊遥博客

承接网站定制|seo优化 :php artisan scout:import "App\Models\Article"大佬,这个会生成什么文件呢

2018-09-17 17:03:45 回复

白俊遥博客 白俊遥博客

云淡风晴 :SQLit 文件  laravel-bjyblog/storage/indexes/articles.index

2018-10-20 22:02:09 回复

白俊遥博客

消失的江湖 :好象英文和数字不能搜索?

2018-07-25 15:50:05 回复

白俊遥博客

偷警车养你啊 :用tp5的集成吗

2018-07-03 15:33:20 回复

白俊遥博客 白俊遥博客

云淡风晴 :这个是 laravel 的;

2018-07-09 00:08:34 回复

白俊遥博客

BLMYX01 白俊遥博客作者大大,想求救一下,我也爆了 这两个错误  Class 'AlgoliaSearch\Version' not found      Class 'AlgoliaSearch\Client' not found   

2018-06-24 21:39:01 回复

白俊遥博客

All of me :执行下 composer require algolia/algoliasearch-client-php   我博客上面有 http://www.shidatuo.online/

2018-06-24 22:01:21 回复

白俊遥博客

All of me :解决了吗??

2018-06-24 22:13:26 回复

白俊遥博客

承接网站定制|seo优化 :你的博客访问不了了  现在报错AlgoliaSearch requires an applicationID

2018-08-17 14:40:18 回复

白俊遥博客

承接网站定制|seo优化 :.env,没有修改成功的原因,我解决了

2018-08-17 15:07:58 回复

白俊遥博客

All of me 白俊遥博客为什么我爆了 这两个错误  Class 'AlgoliaSearch\Version' not found      Class 'AlgoliaSearch\Client' not found

2018-06-23 21:28:23 回复

白俊遥博客 白俊遥博客

云淡风晴 :config/app.php 没有配置?

2018-06-24 19:30:14 回复

白俊遥博客

All of me :我配置了 我解决了谢谢

2018-06-24 19:50:46 回复

白俊遥博客

BLMYX01 :你好,请问你怎么解决的呢,我也出了这个问题orz

2018-06-24 21:34:22 回复

白俊遥博客

BLMYX01 :啊我知道了,没事,打扰啦。。我贪方便直接从另外的地方搞了个配好过的.env弄了上去

2018-06-24 21:44:25 回复

白俊遥博客

All of me :执行下 composer require algolia/algoliasearch-client-php 我的博客 : http://www.shidatuo.online/

2018-06-24 21:58:13 回复

白俊遥博客

All of me :我博客上面有

2018-06-24 21:59:15 回复

白俊遥博客

BLMYX01 :谢谢,学习了!

2018-07-02 01:28:57 回复

白俊遥博客

ωō╄→尛湳 :大佬 博客加个面包屑导航可以吗?这种就完美了!白俊遥博客

2018-06-21 09:46:44 回复

白俊遥博客 白俊遥博客

云淡风晴 :可以是可以的;等我抽出手后就改前端页面;

2018-06-24 19:32:32 回复

白俊遥博客

FineJadeXavier :你好,可以请问一下如何对搜索到的结果进行分页吗?想用ajax滑动加载搜索到结果

2018-06-13 20:53:23 回复

白俊遥博客 白俊遥博客

云淡风晴 :这个分页和模型查询的分页是一样的;

2018-06-24 19:33:37 回复

白俊遥博客

NichoDong :导入也成功了 就是查不出来

2018-06-12 14:19:03 回复

白俊遥博客 白俊遥博客

云淡风晴 :关闭队列试试?

2018-06-24 19:33:50 回复

白俊遥博客

NichoDong :我照着做怎么 查出来是空的呢

2018-06-12 14:18:02 回复

白俊遥博客

星陨、 :我的也是php写的,使用thinkphp5.0框架

2018-06-02 18:26:01 回复

白俊遥博客

星陨、 :你好   我想知道你的评论,是怎么过滤JavaScript代码发布显示的,我的网站,评论留言存在JavaScript注入,可以教一下么,我的网站地址,http://www.xkbooks.com

2018-06-02 18:24:57 回复

白俊遥博客 白俊遥博客

云淡风晴 :我用的这个 https://github.com/mewebstudio/Purifier ;

2018-06-03 22:42:25 回复

白俊遥博客

星陨、 :好的我看看下   谢谢了

2018-06-04 09:17:02 回复

白俊遥博客

星陨、 :alert('test');

2018-06-02 18:21:38 回复

白俊遥博客

星陨、 :alert('test');

2018-06-02 18:20:10 回复

白俊遥博客

星陨、 :              alert('test');             

2018-06-02 18:18:56 回复

白俊遥博客

孤城浪子 :然后 require tntsearch 为 scout 提供的 laravel-scout-tntsearch-driver ;这一句我咋怎么都读不通顺啊......

2018-05-29 21:46:28 回复

白俊遥博客 白俊遥博客

云淡风晴 :然后安装 tntsearch 为 scout 提供的 laravel-scout-tntsearch-driver

2018-06-24 19:35:08 回复

白俊遥博客

神奇大阳阳 :alert('1111');

2018-05-29 16:11:05 回复

白俊遥博客

′ Soulmate :顶顶顶

2018-05-29 15:04:40 回复

白俊遥博客

神奇大阳阳 :大佬大佬。。。。

2018-05-29 14:33:04 回复

白俊遥博客

Larwas 白俊遥博客白俊遥博客白俊遥博客白俊遥博客白俊遥博客白俊遥博客白俊遥博客白俊遥博客

2018-05-29 14:09:42 回复

白俊遥博客

DarrionLi :请先登录后回复评论

2018-08-23 23:51:16 回复

白俊遥博客

承接网站定制|seo优化 :请先登录后回复评论

2020-03-16 15:25:10 回复