laravel / scout

Laravel Scout provides a driver based solution to searching your Eloquent models.
https://laravel.com/docs/scout
MIT License
1.54k stars 329 forks source link

Meilisearch: Sortable and Filterable Attributes not updating when including _geo attribute #555

Closed mxmtsk closed 2 years ago

mxmtsk commented 2 years ago

Description:

To make some attributes filterable and sortable I've written a small artisan command to do the work for me. Now I wanna use Meilisearch's Geosearch functionality. For that, I added _geo to the array of filterable and sortable attributes by using Laravel Scouts respective methods.

It doesn't throw an error but it also doesn't make the attributes filterable or sortable anymore.

This is the code:

    public function handle()
    {
        $client = new Client(config('scout.meilisearch.host'));

        $client->index('pubs')->updateSortableAttributes(['_geo']);
        $this->info('Updated sortable attributes...');

        $client->index('pubs')->updateFilterableAttributes([
            '_geo',
            'cashless_payment',
            'smoking',
            'outside_seating',
            'food',
            'barrierfree',
        ]);
        $this->info('Updated filterable attributes...');

        return Command::SUCCESS;
    }

To check if this is an issue with Meilisearch, I've executed the same command directly on Meilisearch, which worked without a problem:

curl \
  -X POST 'http://localhost:7700/indexes/pubs/settings/filterable-attributes' \
  -H 'Content-type:application/json' \
  --data-binary '[
        "_geo",
        "cashless_payment",
        "smoking",
        "outside_seating",
        "food",
        "barrierfree"
  ]'

{"updateId":2}

curl \
  -X GET 'http://localhost:7700/indexes/pubs/updates/2' \
  -H 'Content-type:application/json'

Update response

{"status":"processed","updateId":2,"type":{"name":"Settings","settings":{"filterableAttributes":["_geo","barrierfree","cashless_payment","food","outside_seating","smoking"]}},"duration":0.047,"enqueuedAt":"2021-11-30T12:46:13.716435Z","processedAt":"2021-11-30T12:46:13.764012Z"}%

Steps To Reproduce:

  1. add the _geo fields to any model:
    public function toSearchableArray()
    {
        $array = $this->toArray();

        $array['_geo'] = [
            'lat' => 52.520008, // hardcoded for reproduction purposes
            'lng' => 13.404954,
        ];

        return $array;
    }
  1. update the filterable attributes:
     $client->index('pubs')->updateFilterableAttributes([
            '_geo',
        ]);
  1. Try to query by Geo Distance
        $params = [
            "latitude" => 52.489769,
            "longitude" => 13.324380
        ];
        $distance = 100000;
        return Pub::search('', function (Indexes $meilisearch, string $query, array $options) use ($params, $distance) {
            $options['filter'] = "_geoRadius({$params['latitude']}, {$params['longitude']}, {$distance})";
            $options['sort'] = [
                "_geoPoint({$params['latitude']}, {$params['longitude']}):asc",
            ];
            return $meilisearch->search($query, $options);
        })->take(10)->get();
mmachatschek commented 2 years ago

@mxmtsk please try to get in touch with a support channel on MeiliSearch Slack they will get you up and running. This issue looks to me like an implementation problem, specific to your usecase.

driesvints commented 2 years ago

Seems like a feature request to me. Feel free to submit a PR or open an issue on the meilisearch repo.

homeoftheunits commented 2 years ago

Hi, i have the same problem. Is there an solution in the meantime?

Cheers Ralf

curquiza commented 2 years ago

Hello @homeoftheunits

You can contact our support (the Meilisearch support) by sharing the detailed steps to reproduce, including the Meilisearch error you get at the final step.

Before contacting us, you might want to check your settings are well being imported to Meilisearch using this route.

homeoftheunits commented 2 years ago

I know. But it looks like, that it's an Scout Problem. I check this

Schipsi commented 2 years ago

Update for those looking for a quick fix :

After looking at Meilisearch logs i found an error during the index :

"The document with the id: `1` contains an invalid _geo field: `{\"lat\":\"52.51667\",\"lng\":\"13.38333\"}`."

When checking the docs, lat and lng are supposed to be float and not string : https://docs.meilisearch.com/learn/advanced/geosearch.html#preparing-documents-for-location-based-search

My guess is that the geo fields are not properly changed back to float when indexed by Meilisearch, casting them to float in the toSearchableArray method fixed this for me. In database the values were stored as float, but that didn't seems to be enough.

Hope this will be useful.

    public function toSearchableArray(): array
    {
        return [
            '_geo' => [
                'lat' => (float) $this->geo_lat,
                'lng' => (float) $this->geo_lng,
            ],
        ];
    }
99linesofcode commented 2 years ago

The solution proposed by @Schipsi resolved the issue for me as well. Without the cast to float my index remains empty despite flushing and updating the indices. Looks to me like an issue with laravel/scout.

curquiza commented 2 years ago

Hello! FYI, once Meilisearch v0.28.0 will be out, this problem will not exist anymore! Just don't forget to update your meilisearch-php client when upgrading your Meilisearch version!

furmannodesol commented 1 year ago

I'm using meilisearch v0.29.0, however the _geo index remains empty despite flushing and updating the indices. tried both by casting as float and string. '_geo' => [ 'lat' => (float) $this->latitude, 'lng' => (float) $this->longitude, ],