Laravel Scout MeiliSearch: Searching IDs with whitespaces

48 views Asked by At

I'm working on integrating Laravel Scout and MeiliSearch into my project, and I've encountered an issue where MeiliSearch doesn't support whitespace characters in the 'id' field. All IDs in my PostgreSQL database, which is synchronized with an external source, contain whitespaces. My scout config:

  'index-settings' => [
            MyModelName::class => [
                'filterableAttributes' => ['id', 'name'],
                'sortableAttributes' => ['created_at'],
            ]
        ],

I attempted to modify the toSearchableArray() method as follows:

  public function toSearchableArray()
    {
        $array = $this->toArray();
        // Replace whitespaces with underscores in the 'id' field
        $data['id'] = trim(str_replace(' ', '_', $array['id']));
        $data['name'] = trim($array['name']);
        return $data;
    }

The importing ends with "All records have been imported." but no documents in the index is created. {{url}}/indexes/{{indexUID}}/stats returns 0 items.

What does seem to work is using attribute casting:

  protected function id(): Attribute
    {
        return Attribute::make(
            get: fn (string $value) => trim(str_replace(' ', '_', $value)),
        );
    }

While this approach allows successful importing, it causes further implications in the app, and the search() method no longer works. I suspect this is because MeiliSearch returns IDs with underscores, and Scout cannot find related entities in the database, as they contain whitespaces instead of underscores.

Any insights on resolving this issue or alternative approaches would be greatly appreciated!

1

There are 1 answers

0
acarspl On

It seems the following Searchable trait functions need to be overriden:

  public function getScoutModelsByIds(Builder $builder, array $ids)
    {
        $ids = array_map(function ($element) {
            return str_replace("_", " ", $element);
        }, $ids);
        return $this->queryScoutModelsByIds($builder, $ids)->get();
    }
    public function getScoutKey()
    {
        return str_replace(" ", "_", $this->getKey());
    }