Используйте более сложные предложения where в Scout

Я счастливый пользователь Laravel Scout.

Теперь я хотел бы расширить свой поиск:

        $data
            = new UserOverviewResourceCollection(User::search($searchphrase)
            ->currentStatus('active')->orderBy('lastname', 'asc')
            ->orderBy('firstname', 'asc')
            ->paginate(config('pagination.length')));

currentStatus берется из https://github.com/spatie/laravel-model-status. .

Теперь я получаю ответ, что currentStatus не поддерживается. Я подумал, что было бы неплохо отфильтровать результат User::search после того, как он был возвращен из разведчика?

Еще одна идея: я хотел бы добавить более сложные предложения where:

->where([
                [
                    'starts_on',
                    '<',
                    Carbon::now()->toDateTimeString(),
                ],
                [
                    'ends_on',
                    '>',
                    Carbon::now()->toDateTimeString(),
                ],
            ])

Может, у тебя есть идея получше?


person SPQRInc    schedule 28.01.2019    source источник


Ответы (4)


Хорошо переписав это, как это должно работать.

 $data
            = new UserOverviewResourceCollection(User::search($searchphrase)
            ->where('starts_on','<',now())
            ->orderBy('lastname', 'asc')
            ->orderBy('firstname', 'asc')
            ->paginate(config('pagination.length')));

Обратите внимание, что now() — это просто глобальная вспомогательная функция, возвращающая текущий момент экземпляра Carbon. Просто писать короче, других причин для его использования нет.

А если вы хотите сгруппировать where запросы, сделайте это следующим образом:

 $data
            = new UserOverviewResourceCollection(User::search($searchphrase)
            ->where(function($q) {
               $q->where('starts_on','<',now())->where('ends_on','>',now())
            })
            ->orderBy('lastname', 'asc')
            ->orderBy('firstname', 'asc')
            ->paginate(config('pagination.length')));

Затем вы сможете экспортировать это в UserOverviewResourceCollection как локальную область действия. , Например:

public function scopeActive($q) {
    return $q->where('starts_on','<',now())->where('ends_on','>',now())
}

а затем вы можете использовать что-то вроде этого:

 $data
            = new UserOverviewResourceCollection(User::search($searchphrase)
            ->active()
            ->orderBy('lastname', 'asc')
            ->orderBy('firstname', 'asc')

Пишу в уме, так что могут быть опечатки.

person brnd0    schedule 28.01.2019
comment
Хм, на самом деле прицел не работает (Method Laravel\\Scout\\Builder::active does not exist). К сожалению, сгруппированное где тоже не работает (laravel.com/docs/5.7/scout# где-предложения) -> Too few arguments to function Laravel\\Scout\\Builder::where(), 1 passed in .. line 91 and exactly 2 expected - person SPQRInc; 28.01.2019
comment
Пойдем по одному шагу за раз. Первый кусок кода работает? Если это не так, можете ли вы удалить часть ->where('starts_on','<',now()) и убедиться, что она работает? - person brnd0; 28.01.2019
comment
Хорошо... Нет, первый фрагмент не работает: сообщение: Неверный синтаксис для числового условия:starts_on=‹, исключение: AlgoliaSearch\\AlgoliaException, файл: /home/vagrant/code/vendor/algolia/algoliasearch-client-php /src/AlgoliaSearch/Client.php, если я удалю пункт where, он сработает. - person SPQRInc; 28.01.2019
comment
laravel.com/docs/5.7/scout#where-clauses Кажется сложным ( что бы это ни значило) запросы не разрешены, поэтому это может быть причиной того, что он не работает. В конечном итоге вы можете попробовать поместить запрос where перед search(), иначе вам, вероятно, придется индексировать поля starts_on и ends_on в Algolia, а затем выполнять запрос через их API. Другим уродливым обходным путем может быть получение идентификатора из Алголии, а затем повторное выполнение запроса к вашей базе данных с использованием whereIn('id',$arrayOfIDsFromAlgolia), но должен быть способ сделать это в Алголии. - person brnd0; 29.01.2019

 $data
        = new UserOverviewResourceCollection(User::search($searchphrase)
        ->currentStatus('active')->orderBy('lastname', 'asc')
        ->where(function($q){
            $query->where('starts_on', '<',Carbon::now()->toDateTimeString());
            $query->where('ends_on', '>',Carbon::now()->toDateTimeString());
         })
        ->orderBy('firstname', 'asc')
        ->paginate(config('pagination.length')));

Попробуйте этот код. Это удовлетворит ваш комплекс, где условие

person Sandeep Sudhakaran    schedule 28.01.2019
comment
Привет и спасибо. К сожалению, он по-прежнему возвращает Method Laravel\\Scout\\Builder::currentStatus does not exist. - person SPQRInc; 28.01.2019
comment
Привет, функция currentStatus написана в самом вопросе. удалите -›currentStatus('active') и попробуйте. - person Sandeep Sudhakaran; 29.01.2019
comment
Да, это написано там не зря - мне это нужно ;-) currentStatus происходит от currentStatus происходит от github.com/spatie/laravel-model-status, как я уже писал в своем первоначальном вопросе :-) - person SPQRInc; 29.01.2019

Мне действительно нужна аналогичная функциональность, но я боюсь, что в данный момент это невозможно (Laravel 8)

Согласно документам; Laravel\Scout\Builder (то, что возвращает search()) имеет только базовую реализацию метода where и может обрабатывать ровно 2 аргумента. Вот код из пакета scout:

/**
 * Add a constraint to the search query.
 *
 * @param  string  $field
 * @param  mixed  $value
 * @return $this
 */
public function where($field, $value)
{
    $this->wheres[$field] = $value;

    return $this;
}

См. https://laravel.com/docs/8.x/scout#where-clauses

Помещение search() позади всех обычных методов красноречивого строителя также не будет работать, поскольку search будет только статической функцией модели.

Надеюсь, это будет улучшено в будущем.

person Arno van Oordt    schedule 28.10.2020

Вы можете расширить Builder и добавить метод currentStatus для сохранения требуемого статуса в Builder. См. пример https://github.com/matchish/laravel-scout-elasticsearch/issues/47#issuecomment-526287359

Затем вам нужно реализовать свой собственный движок и построить запрос, используя конструктор. Вот пример для механизма ElasticSearch: //github.com/matchish/laravel-scout-elasticsearch/blob/06c90914668942b23ffaff7d58af5b9db1901fb1/src/Engines/ElasticSearchEngine.php#L135

person matchish    schedule 03.11.2020