使用 spatie/laravel-query-builder 和 teamtnt/laravel-scout-tntsearch-driver

Use spatie/laravel-query-builder with teamtnt/laravel-scout-tntsearch-driver

我尝试使用laravel tntsearch together with 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 搜索未返回 eloquent 对象,此查询将失败。 有没有办法将这两个包结合起来一起工作?

我完全按照您对 TNTSearch 驱动程序的尝试进行了操作,但我得出了一个艰难的结论,即 Scout 根本不支持默认 QueryBuilder 对象所支持的广泛查询处理。这是设计使然。如果您阅读 Scout 文档,它会清楚地表明您必须先执行搜索 ,然后再 应用您通常会应用的所有 filter/sort 查询。因此,可以这样想:搜索 > 过滤并对搜索结果进行排序。

话虽如此,有可能实现您想要的。它只需要 2 个查询而不是一个。也许有一天 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 查询构建器方法。这是一种将查询编写得更简洁的更聪明的方法,但它等同于编写 QueryBuilder::for(Job::class)->whereIn('id', $searchIds)。当没有搜索时,它会简单地忽略 whereIn 方法。

这会将您的 QueryBuilder 限制为仅与您的搜索匹配的结果,您可以将所有排序和过滤器应用于这些结果。