中文分词介绍
众所周知,英文是以词为单位的,词和词之间是靠空格隔开,而中文是以字为单位,句子中所有的字连起来才能描述一个意思。例如,英文句子I am a student,用中文则为:“我是一个学生”。计算机可以很简单通过空格知道student是一个单词,但是不能很容易明白“学”、“生”两个字合起来才表示一个词。把中文的汉字序列切分成有意义的词,就是中文分词,有些人也称为切词。我是一个学生,分词的结果是:我 是 一个 学生。
应用场景
打个比方,我们要搜索内容字段有“中文分词搜索功能”的文章,用 like 去查询的话,可以匹配以下几种:
like '中文分%'
like '%中文分词搜索功能%'
like '分词搜索功能%'
如果输入 “中文搜索功能”,就无法匹配到对应的文章。这时候就得用中文分词搜索功能了,
分词搜索的原理就是把内容按关键字给拆分,上面那段可以拆分成 “中文”、“分词”、“搜索”、“功能”,然后把这些关键字和内容关联索引,查询结果。
需安装的扩展
pdo_sqlite
sqlite3
mbstring
拉取中文分词的 Laravel Scout TNTSearch 驱动
composer require vanry/laravel-scout-tntsearch
发布 scout 配置文件,已安装 scout 可省略。
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
发布 tntsearch 配置文件。
php artisan vendor:publish --provider="Vanry\Scout\TNTSearchScoutServiceProvider"
添加config/app.php 的 Provider
// TNTSearch 全文搜索
Laravel\Scout\ScoutServiceProvider::class,
Vanry\Scout\TNTSearchScoutServiceProvider::class,
安装结巴分词
jieba 为 python 版本结巴分词的 php 实现,分词效果最好,尤其是新词发现,不足之处是性能较差,占用内存大。
composer require fukuball/jieba-php
.env文件 增加如下配置
SCOUT_DRIVER=tntsearch
# jieba
TNTSEARCH_TOKENIZER=jieba
修改模型
我们是文章表要用到分词搜索,然后作用于标题和内容字段。
<?php
use Laravel\Scout\Searchable;
// ....
class Article extends Model
{
use Searchable;
/**
* Description:索引的字段
* User: Vijay <1937832819@qq.com>
* Date: 2020/07/31
* Time: 10:36
* @return array
*/
public function toSearchableArray()
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => strip_tags($this->content),
];
}
// ...
使用 jieba 分词可能会出现内存分配不足的错误信息:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes)
修改 /app/Providers/AppServiceProvider.php 文件
public function boot()
{
// ...
// 增加内存防止中文分词报错
ini_set('memory_limit', "256M");
}
生成索引
php artisan scout:import "App\Models\Article"
# tntsearch 命令, 性能更好
// php artisan tntsearch:import 'App\Post'