ivone/n2search

dev-master 2022-07-08 03:16 UTC

This package is auto-updated.

Last update: 2023-11-08 05:59:30 UTC


README

logo.png

Laravel N₂Search

为Laravel设计的分词搜索工具

Author badge.svg 68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f69766f6e652d6c69752f6c61726176656c2d736561726368 68747470733a2f2f696d672e736869656c64732e696f2f62616467652ff09f96a57374617475732d646576656c6f70696e672d726564

Github · Packagist · Report Bug


🌟 关于N2Search

LaravelPHP提供了一个优雅使用的框架,无数的开发者为Laravel提供了非常多的工具组件。但是,在我使用的过程中,发现Laravel并没有一个比较好用且灵活调整的搜索工具,无论是官方提供的Scout还是基于Scout延伸出来的其他搜索工具,要么是过重(如:Scout+ElasticSearch方案)要么是不够便捷(如:Scout不支持许多Laravel ORM语法),致使在搜索中非常不方便。

所以,基于以上的问题,我用Jieba作为分词器,单独开发了一套存储在Redis中的分词索引,并且以Laravel ORM链式操作的形式,重新构建了一个Larave可用的便捷搜索工具,确保既能够有效分词,也能方便搜索调用。

🧩 特点

🌀 相比与Scout+数据库查询,效率要高

👨‍💻 可实现中文的拼音搜索

⛓ 支持类似Laravel Eloquent ORM链式操作,无违和感

📊 自动队列支持

🎰 支持多字段查询

🗃 搜索关键词提示

🕹 如何使用

🔧 版本要求

PHP >= 7.0

Laravel >= 8

确保安装Redis

🛠 安装

建议通过Composer来安装

composer require ivone/n2search

🎚️ 配置

composer安装好之后,需要在app/config/app.phpproviders数组中增加N2SearchProvider,如下。

N2Search\N2SearchProvider::class,

然后执行php artisan vendor:publish发布N2Search的配置文件,如果成功,则会在app/config/目录中看到N2Search.php文件。

return [
    'redis_host'        => env('REDIS_HOST', '127.0.0.1'), // REDIS服务IP地址
    'redis_password'    => env('REDIS_PASSWORD', null), // REDIS密码
    'redis_port'        => env('REDIS_PORT', '6379'), // REDIS端口
    'redis_db'          =>  9, // 给N2Search提供的可用REDIS库
    'pinyin'            =>  1, // 1启动中文拼音检索 0关闭中文拼音检索
    'dict'              => 'big', // 分词词典,默认big,可选:small
    'job_work'          => 0, // 启用队列支持,可在导入时选用,默认0关闭,可选:1开启
    'stop_words'        =>  [] // 不分词词语配置
];

📈 开始构建索引

你可以在你的Laravel项目中新建一个Command,用命令行形式把你的数据表重新构建成搜索索引,便于你自定义你的索引关系。

$count = YourModel::count();
$bar = $this->output->createProgressBar($count);

$n2 = new N2Search();
$logs = YourModel::get()->toArray();
foreach ($logs as $log) {
    $n2->load(YourModel::class, ['content'])->addOne($log['id']);
    $bar->advance();
}

$bar->finish();

或者直接执行N2Search自带的Command

php artisan n2search:build {Your Model Class:App\\Model\\LogModel(etc)}

其中,以下两行代码是导入生成搜索分词索引的。

$n2 = new N2Search();
$n2->load(YourModel::class, ['content'])->addOne($log['id']);

load(Model的Builder构造器,以及对应Model中要构建索引的字段);

addOne是指仅添加一条数据,需要额外增加ID主键参数。

addBatch是可以一次性添加整个Model的所有数据,无需其他参数。

🔍 关键词查询

在完成第一步导入数据之后,就可以尝试从已构建的分词索引中查询数据了。

$n2 = new N2Search();
$n2->find(YourModel::class, '我')->columns(['name', 'degree'])->where(['user_id'=>1])->where(['relation_id'=>101])->page(1, 20)->order('id', 'desc')->fetchMany();
$n2->find(YourModel::class, '好的')->columns(['name', 'degree'])->where(['user_id'=>1])->order('id', 'desc')->fetchOne();

如果使用了fetchMany(),后面增加了data()方法来返回查询结果的数组,fetchOne()不支持。

$n2 = new N2Search();
$n2->find(YourModel::class, '我')->columns(['name', 'degree'])->where(['user_id'=>1])->where(['relation_id'=>101])->page(1, 20)->order('id', 'desc')->fetchMany()->data();

其中

fetchMany()表示一次性读取多条数据,如Laravel get()

fetchOne()表示一次只读一条数据,如Laravel first()

查询主要参考了Laravel ORM的链式操作设计,可以多次绑定查询条件,并生成查询结果。N2Search的查询结果类型是Array

🗑 删除/清理

$n2 = new N2Search();
$n2->clear()->flush();
$n2->clear()->remove($key1, $key2, $key3 ...);

或者直接执行N2Search自带的Command全部清理。

php artisan n2search:clear

flush 方法对应 Redis 中的 flushdb方法,清空在配置中 redis_db 中的所有内容

remove 是删除指定关键词,其中的$key参数可传任意长度

👏 完成

基础查询已经完成,你可以拿到N2Search提供的查询结果做你想做的逻辑处理了,更高级的功能和使用会在下文中逐一介绍。

💡 高级

🔤 拼音

参考开始构建索引

在项目publish之后,config目录下的N2Search.php中,pinyin一项改为1即可,0表示不转拼音。

🏳️‍🌈 多语言

开发中

🧳 队列

首先确保你的Laravel队列配置正确,如果是同步队列导入效率并不会有太大的变化,建议使用异步队列

我本地用的是CentOS虚拟机,使用Supervisor做的队列守护进程,推荐一下

默认队列是n2_build,如果你的机器资源足够,可以多开几个队列。

建议:

  • 无需设置失败重试
  • 尽量设置较高的内存分配(>=2048M)
  • 2个以上的队列效果会比较明显

🗃 搜索关键词提示

开发中

🧮 权重计算

针对关键词的权重计算,不存在于fetchOne()场景中,仅对fetchMany()增加了对关键词在不同文档中的权重。

fetchMany()方法之后,以链式操作的形式,后面追加analysis()方法,可返回关键词在文档中的权重,字段名为n2_weight

🧑🏻‍💻 联系我

你可以在github中给我提issue,或者邮件联系我:i@ivone.me

友情链接:方寸笔迹