【问题标题】:Use spatie/laravel-query-builder with teamtnt/laravel-scout-tntsearch-driver将 spatie/laravel-query-builder 与 teamtnt/laravel-scout-tntsearch-driver 一起使用
【发布时间】:2021-01-08 12:43:52
【问题描述】:

我尝试将laravel tntsearchspatie 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 的对象,这个查询将失败。 有没有办法将这两个包组合在一起工作?

【问题讨论】:

    标签: laravel search eloquent fuzzy-search


    【解决方案1】:

    我完全按照您尝试使用 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 查询构建器方法。这是一种更聪明的方式来编写更简洁的查询,但它相当于编写QueryBuilder::for(Job::class)->whereIn('id', $searchIds)。当没有搜索时,它会简单地省略whereIn 方法。

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

    【讨论】:

    • 非常感谢您的反馈!起初尝试似乎有效。我将进行一些测试。
    • 感谢您的回答。我使用Job::search($this->search)->keys() 来获取ID,它比检索完整对象集合和使用pluck() 更快。
    • 这是一个很好的观点。我将更新我的答案以改用它。
    猜你喜欢
    • 2018-10-26
    • 1970-01-01
    • 2021-01-09
    • 1970-01-01
    • 2015-04-30
    • 2021-01-18
    • 2021-08-20
    • 2020-08-09
    • 2020-03-17
    相关资源
    最近更新 更多