0

I already had this "problem" when using a local scope in the same model but i used another method to reach that specific goal.

Now, i want use MeiliSearch as search engine but i have the same problem as above: the paginated result are being truncated. The pagination is set to 10. The first page has 6 results, the second one has 2 results and the fourth page has 0 results.

Article::search($this->meiliSearchText)
    ->query(fn($query) => ($this->showSold == "true" ? $query->whereHas('sales') : ($this->showSold == "false" ? $query->whereDoesntHave('sales') : $query)))
    ->paginate($this->pagination)

I think this is cause because a filter is applied AFTER the query has been retrieved. How should i treat this aspect?

EDIT:

In the documentation it's explicitly said that the "query" method should not be used for filtering result and i should use the Laravel Scout's "where" clause.

Since this callback is invoked after the relevant models have already been retrieved from your application's search engine, the query method should not be used for "filtering" results. Instead, you should use Scout where clauses.

But honestly i can't get it to work even with that useless piece:

Article::search($this->meiliSearchText)
    ->where(function ($query) { return $query; })
    ->paginate($this->pagination),

It simply kills the page returning a 500 error.

EDIT 2:

Well.

Since a search index is not a relational database, more advanced "where" clauses are not currently supported.

Musamba
  • 35
  • 1
  • 7

1 Answers1

0

Try query() by this way:

$query = Article::query();

$query->when($this->showSold == "true", function($q){
    $q->has('sales');
});

$query->when($this->showSold == "false", function($q){
   $q->doesntHave('sales');
});

$articales = $query->paginate($this->pagination);

and if you want to use search local scope then you can add that scope in fist line right after the query(). i.e.

$query = Article::query()->search($this->meiliSearchText);

if search still not work accordingly then move search() before the query() builder. i.e.

$query = Article::search($this->meiliSearchText)->query();

Note please verify true and false is string or boolean type value and then compare those accordingly. if there type is string then enclosed a value in double quotes or if boolean then remove those double quotes.

M-Khawar
  • 855
  • 5
  • 17
  • The first block works pretty well! I never use the "never" clause, thanks for this new tip! The second one gives "Call to undefined method Illuminate\Database\Eloquent\Builder::search()" while the third returns "Too few arguments to function Laravel\Scout\Builder::query(), 0 passed" – Musamba Jun 23 '22 at 07:52
  • have you imported `Laravel\Scout\Searchable;` in Article model and also added `Searchable` trait in class or not? [Laravel scout installation reference](https://laravel.com/docs/9.x/scout#installation). I hope that will work if you follow same installation procedure – M-Khawar Jun 23 '22 at 09:41
  • Yes, anything installed. The search itself is not a problem but filtering the result with other fields other than simple text search. – Musamba Jun 23 '22 at 10:08
  • hey have you tried `search()` before the `paginate()` because I think `search()` convert results to collection so you need to place filters before the `search()` i.e. `$articales = $query->search($this->meiliSearchText)->paginate($this->pagination);` – M-Khawar Jun 23 '22 at 11:32
  • Paginate should always be the last chained method when paginating i think – Musamba Jun 29 '22 at 10:27