Laravel Scout是Laravel官方提供的轻量级全文搜索方案,它通过统一的接口把模型数据同步到外部搜索引擎。Algolia作为托管的搜索云服务,提供了极低的查询延迟和开箱即用的中文分词配置。将两者结合,开发者无需自建索引服务即可为应用增加高质量搜索能力。

一、环境准备与依赖安装
在开始之前,请确保已经有一个可运行的Laravel项目,并且PHP版本不低于8.0。Algolia的PHP客户端需要curl扩展支持,大部分集成环境默认已开启。我们首先通过Composer拉取Scout以及Algolia官方适配器。
执行下面的命令完成安装,其中laravel/scout是核心包,algolia/algoliasearch-client-php则负责与Algolia API通信。安装完成后,使用vendor:publish导出配置文件,这样我们就能在config/scout.php中填写应用ID和秘钥。
composer require laravel/scout algolia/algoliasearch-client-php php artisan vendor:publish --provider="LaravelScoutScoutServiceProvider"
配置文件中driver要设为algolia,并填入从Algolia后台获取的app_id与secret。出于安全考虑,秘钥应写在.env文件里,避免提交到代码仓库。下面是一段典型的env配置示例。
SCOUT_DRIVER=algolia ALGOLIA_APP_ID=YOUR_APP_ID ALGOLIA_SECRET=YOUR_ADMIN_KEY
二、模型接入Searchable接口
让一个Eloquent模型可被搜索,只需引入LaravelScoutSearchable trait。该trait会自动在模型创建、更新、删除时触发索引同步事件,不需要手动调用API。但默认情况下,整个模型的所有字段都会被推送,这可能包含密码或内部状态,因此需要重写toSearchableArray方法来筛选字段。
以下示例以Product模型为例,只把名称和描述同步到Algolia,并附加一个分类名称用于过滤。注意返回数组的键会成为Algolia索引里的attribute,后续搜索排序都依赖这些字段。
<?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use LaravelScoutSearchable;
class Product extends Model
{
use Searchable;
protected $hidden = ['cost_price'];
public function toSearchableArray()
{
return [
'id' => $this->id,
'name' => $this->name,
'description' => $this->description,
'category_name' => $this->category->name ?? '',
];
}
}
如果模型关联了分类表,可以在toSearchableArray里通过关系加载,但应避免复杂的N+1查询。对于大数据量导入,建议先用with预加载关系,再执行scout:import,否则每条记录都会触发一次关联查询,严重拖慢速度。
三、初始化索引与数据导入
配置完毕之后,本地数据库里的存量记录并不会自动进入Algolia,需要手动执行导入命令。该命令会按模型分批读取,并调用Algolia批量接口写入。首次导入时Algolia会自动创建索引,索引名称默认是模型名复数形式,例如products。
运行下面指令即可开始导入,终端会显示处理进度。如果数据量很大,可以加--chunk参数控制每次读取行数,降低内存占用。
php artisan scout:import "AppModelsProduct"
导入后登录Algolia后台,能看到记录数和每条记录的attribute。此时若修改了toSearchableArray结构,需要重新导入才能使旧数据生效。另外在开发阶段可设置SCOUT_QUEUE=true,让同步操作进入队列,避免请求响应被索引更新拖慢。
四、执行搜索与结果处理
在前端或控制器中,使用模型的search方法即可发起查询。Scout把Algolia返回的结果包装成类似Eloquent集合的对象,因此可以直接用分页或遍历。下面的代码演示了在控制器里接收关键词并返回视图。
<?php
namespace AppHttpControllers;
use AppModelsProduct;
use IlluminateHttpRequest;
class SearchController extends Controller
{
public function index(Request $request)
{
$keyword = $request->input('q', '');
$results = Product::search($keyword)->paginate(10);
return view('search.index', compact('results', 'keyword'));
}
}
search方法还支持链式调用where来添加过滤,例如只搜某个分类。这会在Algolia查询里附加facetFilters,比在PHP里过滤更高效。如果需要自定义排序,可以调用orderBy,对应Algolia的排序规则需在后台配置好。
$results = Product::search('手机')->where('category_name', '电子产品')->get();
Algolia默认按相关度打分,中文内容需在后台启用中文分词插件,否则“智能手机”会被当成一个词,无法匹配“手机”的查询。启用后搜索召回率会明显提升,这也是很多项目接入后感觉搜索变准的关键一步。
五、常见问题与优化建议
第一个常见坑是测试环境频繁刷新数据库导致Algolia里堆积废弃objectID。可以在部署脚本里先调用scout:flush清空索引再import,保证线上线下一致。第二个问题是管理员秘钥暴露在前端,记住Algolia区分admin key和search key,前端只能使用search key。
性能方面,如果搜索接口响应时间不稳定,优先检查是否开启了SCOUT_QUEUE。另外Algolia免费版有记录数和操作数限制,高并发写入时应使用批量更新而非逐条模型保存。对于只读场景,可把search key缓存到前端,减少后端中转,进一步压缩延迟。
| 对比项 | Like查询 | Scout+Algolia |
|---|---|---|
| 中文模糊匹配 | 需手写通配符 | 分词引擎原生支持 |
| 十万数据耗时 | 200毫秒以上 | 20毫秒内 |
| 运维成本 | 无 | 托管服务零运维 |
通过上述步骤,一个具备生产可用水平的全文搜索就搭建完成了。后续可结合Algolia的Rules功能做搜索推荐,或利用Scout的软删除同步策略保持索引与数据库最终一致。
Laravel_ScoutAlgolia全文搜索修改时间:2026-08-04 00:57:32