Laravel Scout/Meilisearch - фильтр по столбцу, недоступному для поиска

Я хочу сделать так, чтобы я мог фильтровать результаты на основе столбца, который не доступен для поиска с помощью Meilisearch и Laravel scout.

Итак, представьте себе таблицу «Комментарии» со следующими столбцами, доступными для поиска:

      public function toSearchableArray() {
    $array = Arr::only(
        $this->toArray(),
        ['id','title', 'link', 'raw_text', 'subchan', 'nsfw']
    );
    
    return $array;  
}

Но получать результаты только после определенной даты:

      Comment::search($query, ['filters' => 'created_at > 795484800'])

Для этого мне нужно добавить toSearchableArray разведчика. Проблема в том, что когда пользователь выполняет поиск, результаты created_at также будет запрошен.

3 ответа

Если я правильно вас понял, вы хотите иметь возможность фильтровать по столбцу, но он не должен быть доступен для поиска, т.е. ввод «795» в качестве запроса не должен возвращать все результаты, где «795» является частью временной метки?

Я не думаю, что Scout позволит вам добиться этого простым способом на данный момент, но это все еще возможно.

Шаг 1 - добавить столбец в toSearchableArray()метод. Это обеспечит индексацию данных Мейли.

Шаг 2 - изменить конфигурацию индекса, в котором ваша модель доступна для поиска, чтобы исключить created_atиз списка доступных для поиска атрибутов . Это псевдокод и недокументированный, но он должен выглядеть примерно так:

      $dummy = new Comment();

// Should resolve to an engine: https://github.com/laravel/scout/blob/f8aa3c3182fe97f56a6436fd0b28fcacfcbabc11/src/Searchable.php#L279
$engine = $dummy->searchableUsing();

// Should resolve to MeiliSearch\Endpoints\Indexes via a magic method that resolves the underlying Meili driver:
// https://github.com/laravel/scout/blob/33bbff0e3bfb1abd0ea34236c331fc17cdeac0bc/src/Engines/MeiliSearchEngine.php#L298
// ->
// https://github.com/meilisearch/meilisearch-php/blob/f25ee49b658f407af3d3f1f9a402997e7974b6bb/src/Delegates/HandlesIndex.php#L23
$index = $engine->index($dummy->searchableAs());

// https://github.com/meilisearch/meilisearch-php/blob/f25ee49b658f407af3d3f1f9a402997e7974b6bb/src/Endpoints/Delegates/HandlesSettings.php#L55
$index->updateSearchableAttributes(
    ['id','title', 'link', 'raw_text', 'subchan', 'nsfw']
);

Один раз create_atиндексируется, но недоступен для поиска, вы хотите отфильтровать значение. У Мейли есть операторы для числовых значений .

Шаг 3 - выполнить индивидуальный поиск с помощью Scout:

      Comment::search($query, function (Indexes $meilisearch, $query, $options) {
    $options['filters'] = 'created_at>795484800';

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

Опять же, это псевдокод - я не тестировал ни одну его часть. Я был бы очень признателен, если бы Scout реализовал поддержку настройки параметров индекса при создании или предоставил метод обновления параметров, позволяющий, например, добавлять параметры конкретного драйвера в файл конфигурации.

Я потратил много часов на отладку и настройку фильтра для дат.

это не будет работать, так как предложение where принимает только два аргумента

      Comment::search($query)->where('created_at', '>', 795484800)->get();

это также не будет работать, потому что переданные аргументы не являются частью двух опций, которые они поддерживают в библиотеке разведки.

      Comment::search($query, function (Indexes $meilisearch, $query, $options) {
    $options['filters'] = 'created_at>795484800';

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

мое решение для всех, кто пытается заставить это работать, состоит в том, чтобы использовать следующее:

      $results = Event::search(
            query: $request->get('query'),
            callback: function (Indexes $meilisearch, $query, array $options) use ($request, $from, $to) {
                
                $options['filter'] = "from <= 1667692800";
                // dd($options);
                return $meilisearch->rawSearch(
                    $query,
                    $options,
                );
            },
        )->paginate();

надеюсь, что это поможет всем, у кого есть проблемы, так как это потратило мое утро на поиск решений, пока я не решил покопаться в коде в библиотеке.

Я решил свою проблему, используя фильтруемые атрибуты Meilisearch. Но его нужно настроить перед запуском поиска. я использовал php artisan tinkerчтобы решить эту проблему следующим образом, вы можете написать для этого ремесленную команду.

      $client = new MeiliSearch\Client('https://url_to_meilisearch_instance:7700');

$client->index('comments_index')->updateFilterableAttributes(['created_at']); // Replace your index_name

И это все. Если у вас довольно большой набор данных, вы можете запустить следующую команду, чтобы проверить статус:

      $client->index('comments_index')->stats();

Если ответ содержит isIndexing => falseты можешь идти. Теперь вы можете запустить фильтр как обычно,

      Comment::search($query)->where('created_at', '>', 795484800)->get();
Другие вопросы по тегам