I try to use laravel tntsearch together with spatie query builder. Based on Spatie Query Builder documentation I try to build my query as it follows
if($request->has('kw')) {
$keyword = response()->json($request->get('kw'));
$query = Job::search($keyword);
} else {
$query = new Job();
}
$result = QueryBuilder::for($query)
->paginate()
->query();
as laravel tnt search is not returning an eloquent object this query will fail. Is there a way to combine the 2 packages to work together?
I did exactly what you are trying to do with the TNTSearch driver and I came to the difficult conclusion that Scout simply does not support the wide range of query handling that the default QueryBuilder object does. This is by design. If you read the Scout documentation, it makes it clear that you have to perform the search before you apply all the filter/sort queries you normally would. So, think of it this way: Search > filter and sort the results of the search.
That being said, it is possible to achieve what you're wanting. It just requires 2 queries instead of one. Maybe some day Scout will get better support for this.
Here's how I did it:
Set a variable to hold your search result ids
$searchIds = blank($request->kw) ? [] : Job::search($this->search)->keys();
searchIds
is now either an empty array or an array of model ids. Now you can utilize Spatie's QueryBuilder object to apply your filters and sorts.
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();
In the above example we're using the tap
method to conditionally chain on the whereIn
query builder method. It's a more clever way to write the query a little cleaner but it is the equivalent of writing QueryBuilder::for(Job::class)->whereIn('id', $searchIds)
. When there is not a search it will simply omit the whereIn
method.
This will limit your QueryBuilder to only results matching your search and you can apply all your sorts and filters to those results.