laravel - 使用 spatie/laravel-query-builder 和 teamtnt/laravel-scout-tntsearch-driver
问题描述
我尝试将laravel tntsearch与spatie query builder一起使用。基于 Spatie Query Builder 文档,我尝试按照以下方式构建我的查询
if($request->has('kw')) {
$keyword = response()->json($request->get('kw'));
$query = Job::search($keyword);
} else {
$query = new Job();
}
$result = QueryBuilder::for($query)
->paginate()
->query();
由于 laravel tnt 搜索没有返回一个雄辩的对象,这个查询将失败。有没有办法将这两个包结合起来一起工作?
解决方案
我完全按照您尝试使用 TNTSearch 驱动程序执行的操作,我得出了一个艰难的结论,即 Scout 根本不支持默认 QueryBuilder 对象所做的广泛的查询处理。这是设计使然。如果您阅读 Scout 文档,就会清楚地表明您必须先执行搜索,然后才能应用所有通常会使用的过滤器/排序查询。所以,这样想:搜索 > 过滤和排序搜索结果。
话虽如此,有可能实现您想要的。它只需要 2 个查询而不是 1 个。也许有一天Scout会得到更好的支持。
我是这样做的:
设置一个变量来保存您的搜索结果 ID
$searchIds = blank($request->kw) ? [] : Job::search($this->search)->keys();
searchIds
现在要么是一个空数组,要么是一个模型 ID 数组。现在您可以利用 Spatie 的 QueryBuilder 对象来应用您的过滤器和排序。
QueryBuilder::for(Job::class)
->allowedFilters([
// your filters go here
])
->allowedSorts([
// your sorts go here
])
->tap(function ($query) use ($searchIds) {
return empty($searchIds) ? $query : $query->whereIn('id', $searchIds);
})
->paginate();
在上面的示例中,我们使用该tap
方法有条件地链接whereIn
查询构建器方法。这是一种更聪明的方式,可以将查询编写得更简洁一些,但它相当于 write QueryBuilder::for(Job::class)->whereIn('id', $searchIds)
。当没有搜索时,它将简单地省略该whereIn
方法。
这会将您的 QueryBuilder 限制为仅与您的搜索匹配的结果,并且您可以将所有排序和过滤器应用于这些结果。
推荐阅读
- angular - Modify dateformat angular datepicker
- python - 在 Pandas Dataframe 中将 Datetime 对象存储为 IsoDate
- angular - routerLinkActive 在第一次加载时没有醒来
- visual-studio - 通过 Visual Studio 调试 Electron 渲染器进程
- android - 根据两个类定义扩展方法?
- sql - sql使用count接收所有信息
- user-interface - PyQt UI 在新窗口中显示,但小部件不激活信号
- kubernetes - 使用 envoy 或 istio 向传出请求注入凭据
- javascript - 使用 React 进行动态服务器端渲染?
- sql - 连接到 SQL Server 实例 AWS Glue