在Laravel 10+Laravel Scout中如何用Meilisearch实现数组排除过滤?
解决Laravel Scout + Meilisearch 排除数组交集条目的问题
核心思路
利用Meilisearch对数组类型字段的原生过滤支持,通过NOT IN语法排除与传入分类ID数组存在交集的条目,关键是确保字段被正确配置为可过滤属性。
步骤1:确保索引字段配置正确
- 模型中返回数组字段
在你的模型的toSearchableArray方法中,确保denied_categories以整数数组形式被加入索引:
public function toSearchableArray() { $data = $this->toArray(); // 若denied_categories是关联数据,可自行处理为整数数组后赋值 $data['denied_categories'] = $this->denied_categories; return $data; }
- 将字段设为可过滤属性
Meilisearch需要明确标记可过滤字段,你可以通过两种方式设置:
- 代码方式(建议仅初始化时执行):
// 在模型的boot方法中添加,执行一次后可注释 public static function boot() { parent::boot(); static::saving(function () { static::searchableUsing()->updateFilterableAttributes([ // 保留现有可过滤字段,新增denied_categories 'denied_categories', // 其他业务所需可过滤字段... ]); }); }
- 控制台方式:进入Meilisearch Dashboard,找到对应索引的
Settings -> Filterable Attributes,添加denied_categories。
步骤2:构建过滤查询
在业务代码中,接收前端传入的分类ID数组,通过Scout的filter方法传入Meilisearch原生过滤条件:
// 接收前端参数并转为安全的整数数组 $blockedCategories = array_map('intval', request()->input('blocked_categories', [])); $query = YourModel::search(''); // 仅当数组非空时添加过滤条件,避免无效语法 if (!empty($blockedCategories)) { $filter = sprintf('NOT denied_categories IN [%s]', implode(',', $blockedCategories)); $query->filter($filter); } // 获取最终结果 $results = $query->get();
原理说明
denied_categories IN [1,2,3]:匹配所有denied_categories数组中包含1、2或3的文档- 加上
NOT前缀后,会直接排除这些与传入数组存在交集的文档,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Antoine Kurka
相关产品推荐
相关产品推荐

