使用Laravel Scout+Meilisearch为何仍触发Eloquent查询?
问题原因与解决方案
为什么会触发MySQL查询?
Laravel Scout 默认的工作逻辑是:
- 先调用 Meilisearch 获取匹配的模型ID列表
- 再通过这些ID去数据库查询完整的 Eloquent 模型实例
这就是你在 Telescope 中看到select * from users where users.id in (1, 2, 3)的原因——Scout 设计的初衷是让你能继续使用 Eloquent 的关联、模型方法等特性,所以默认会把搜索结果转换成标准的 Eloquent 模型对象。
如何直接从 Meilisearch 获取数据?
如果不需要 Eloquent 模型,只想直接拿到 Meilisearch 返回的原始数据,有两种可行方式:
1. 使用 raw() 方法
把代码中的get()替换成raw(),它会直接返回 Meilisearch 的响应结果,不会触发任何数据库查询:
$this->results = User::search($query, function ($meili_search, string $query, array $options) use ($request, $sort_field, $sort_direction) { $options['offset'] = PaginatorHelper::offset($request->page ?? 1, $request->per_page); $options['limit'] = intval($request->per_page); $options['sort'] = [$sort_field .':' . $sort_direction]; return $meili_search->search($query, $options); })->raw();
2. 确保索引包含所需字段
要让raw()返回完整可用的数据,需要在User模型的toSearchableArray()方法中定义所有需要的字段,确保它们被同步到 Meilisearch 索引中:
public function toSearchableArray() { return [ 'id' => $this->id, 'name' => $this->name, 'email' => $this->email, // 添加你需要从Meilisearch获取的其他字段 ]; }
补充说明
如果仍然需要使用 Eloquent 模型但想优化查询,可以:
- 尽可能在索引中包含更多字段,减少数据库查询的必要性
- 使用 Scout 的
load()方法预加载关联,优化数据库查询次数(但仍会触发查询)
内容的提问来源于stack exchange,提问作者Винсентэ Пуххини
相关产品推荐
相关产品推荐

