使用Laravel Scout/Meilisearch时search后加where过滤子句报错如何解决?
问题原因
你遇到的报错是Laravel Scout + 旧版Meilisearch的过滤语法不兼容、配置缺失导致的,核心问题有两个:
- Laravel Scout的
search()方法返回的是Scout查询构造器,不能直接混用Eloquent原生的where()逻辑,直接链式调用会触发语法冲突/逻辑错位 - Meilisearch 0.22版本需要显式声明可过滤字段,未提前配置的字段传入过滤规则会直接报错
解决方案
1. 配置Product模型的可过滤字段
在你的Product模型中添加如下配置,声明store_id为可过滤字段,同时确保toSearchableArray()方法返回的数组包含store_id:
<?php namespace App\Models; use Laravel\Scout\Searchable; use Illuminate\Database\Eloquent\Model; class Product extends Model { use Searchable; // 声明可过滤字段,Scout会自动同步到Meilisearch的过滤属性配置 protected $filterable = [ 'store_id', ]; // 可选:如果上面的配置不生效,可以重写该方法 public function getFilterableKeys(): array { return ['store_id']; } // 确保搜索数组包含store_id public function toSearchableArray() { $array = $this->toArray(); // 保留你原有逻辑,确保store_id在返回数组中即可 return $array; } }
配置完成后执行命令同步已有数据到Meilisearch:php artisan scout:import "App\Models\Product"
2. 正确编写搜索过滤代码
两种适配旧版本的写法可直接使用:
// 写法1:用Scout原生where方法(推荐) $products = Product::search($搜索关键词) ->where('store_id', 你要筛选的门店ID) ->get(); // 写法2:手动传入过滤规则适配0.22版Meilisearch(写法1报错时用) $products = Product::search($搜索关键词, function ($engine, string $query, array $options) use ($storeId) { $options['filter'] = "store_id = {$storeId}"; return $engine->search($query, $options); })->get();
注意事项
- 不要在
get()之后再调用where,这种写法是在PHP内存中对结果集合做过滤,数据量大时性能极差 - 不要在搜索链式调用中混用Eloquent的数据库查询方法(比如关联查询、数据库层的where条件),如果需要做数据库层二次过滤,可以先拿到Meilisearch返回的主键数组,再单独做Eloquent查询
内容的提问来源于stack exchange,提问作者Pedro Abreu
相关产品推荐
相关产品推荐

