Subham Manna
Subham Manna

Reputation: 93

Laravel Scout with Meilisearch filtering not working with >, >=, <, and <= operators

I am trying to implement Meilisearch on my Laravel application.

for some reason I'm not able to filter decimal fields (price, mrp etc..) using >, >=, <, and <= operators as explained on Meilisearch Documentation.

        Product::search($request->search, function ($meilisearch, $query, $options) {
            $options['filter'] = 'price >= 1'; // This is the line that causes the issue.
            return $meilisearch->search($query, $options);
        })->raw();

If I do something like above, I get 0 hits, altho there are many records that satisfy that condition (price >= 1):

I'm not sure what I'm doing wrong.


Also, I want to learn , how can I apply multiple fiters. Like, in actual scenario. we need to filter the products by min and max price. I realized that Laravel scout doesn't allow us to use advanced where clauses (where('price', '>=', $request->min_price)) like eloquent

I want to do something like this using Scout and Meilisearch.

        $query = Product::search($request->search);
        
        if ($request->min_price) {
            $query->where('price', '>=', $request->min_price);
        }
        if ($request->max_price) {
            $query->where('price', '<=', $request->max_price);
        }

Upvotes: 1

Views: 1856

Answers (2)

Andy Stafford
Andy Stafford

Reputation: 1

The current documentation details how to achieve this, although not in the most obvious way https://laravel.com/docs/11.x/scout

use Algolia\AlgoliaSearch\SearchIndex;
use App\Models\Order;
 
Order::search(
    'Star Trek',
    function (SearchIndex $algolia, string $query, array $options) {
        $options['body']['query']['bool']['filter']['geo_distance'] = [
            'distance' => '1000km',
            'location' => ['lat' => 36, 'lon' => 111],
        ];
 
        return $algolia->search($query, $options);
    }
)->get();

So you can do

Product::search('', function (Meilisearch\Endpoints\Indexes $search, string $query, array $options) use ($filters) {
        $options['filter'] = <<<'EOT'
product.status IN ['Editing', 'Approved', 'Published', 'Excluded'] 
AND
product.price > 50
EOT;

        return $search->search($query, $options);
    })

Upvotes: 0

derHofbauer
derHofbauer

Reputation: 61

A hacky way that we are using at the moment is to place the operator into the field:

    $query = Product::search($request->search);
        
    if ($request->min_price) {
        $query->where('price >', $request->min_price);
    }
    if ($request->max_price) {
        $query->where('price <', $request->max_price);
    }

That way Scout creates the proper (e.g. price >= {min_price}) expression. But beware that this is just workaround and does not necessarily work with other search engines supported by Scout.

Please watch Scout's Meilisearch driver for why this works: https://github.com/laravel/scout/blob/9.x/src/Engines/MeiliSearchEngine.php#L163-L188

Upvotes: 6

Related Questions