Как быстро загружать агрегаты в Laravel с помощью Eloquent? - PullRequest
0 голосов
/ 06 марта 2020

в моем приложении у меня длинный список категорий. Я загружаю их с этим:

$categories = Categories::all();

В Categories есть эта функция:

public function transactions()
{
    return $this->hasMany(Transactions::class);
}

public function getPreviousActivityAttribute() {
    return $this->transactions()
        ->where('date', '<' Carbon::now()->firstOfMonth())
        ->sum('amount');
}

Я отображаю этот список категорий в виде таблицы. Каждая строка вызывает $category->previousActivity.

Это приводит к n + 1 запросам к базе данных, где n - количество категорий (и их много). Помимо previousActiviy я также показываю другие агрегаты (некоторые делают SUM другие делают AVG, и т.д. c.).

Кстати. Есть много транзакций. Я не могу загрузить их все, используя Categories::with('transactions')->get(). Это потребует слишком много памяти.

Есть ли способ увеличить нагрузку агрегатов? В построителе запросов есть метод withCount, но здесь он не очень помогает.

Спасибо за помощь.

Ответы [ 2 ]

0 голосов
/ 09 марта 2020

Присоедините функцию к атрибуту withCount в конструкторе модели, как это, чтобы всегда стремиться загрузить это количество.

public function __construct(array $attributes = array())
{
    parent::__construct($attributes);

    $this->withCount['transactions as total'] = function ($query) {
        $query->select(DB::raw(
            'SUM(IFNULL(amount, 0)) as relationsum'
        ));
    };
}
0 голосов
/ 06 марта 2020

Чистым решением было бы использовать withCount следующим образом:

В категориях. php:

public function withPreviousActivity()
    {
        return $this->withCount([
            'transactions as previous_activity' => function ($query) {
                $query->select(DB::raw("SUM(IFNULL(amount,0)) as transactions_count"))->where('date', '<', Carbon::now()->firstOfMonth());
            },
        ]);
    }

Где-то еще:

dump(Categories::withPreviousActivity()->get()->toArray());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...