@drnkwtr
forblitz.ru dev

Как правильно организовать выборку в коллекции / N+1 проблема?

Использую Resource Collection для вывода данных в API Laravel, однако при запросе files с условием type == mod, возникает N+1 проблема с запросами. Как её решить или правильнее организовать выборку из коллекции?

ModController:
public function index()
    {
        $mods = Mod::with('categories')
            ->with('mod_author')
            ->with('files')
            ->paginate('10');

        return ModResource::collection($mods);
    }

ModResource:

public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'author' => new AuthorResource($this->mod_author),
            'sticky' => $this->sticky,
            'categories' => CategoryResource::collection($this->categories),
            'files' => [
                'archives' => File::where('type', 'mod')->where('mod_id', $this->id)->get(),
             ]
        ];
    }


6320fdf22c9b7036755602.jpeg
  • Вопрос задан
  • 107 просмотров
Решения вопроса 2
iMedved2009
@iMedved2009
Не люблю людей
Вариант 1
public function index()
    {
        $mods = Mod::with('categories')
            ->with('mod_author')
            ->with(['files' => function($query){
return $query->where('type', 'mod');
}])
            ->paginate('10');

        return ModResource::collection($mods);
    }
public function toArray($request)
    {
        return [
            'id' => $this->id,
            'title' => $this->title,
            'slug' => $this->slug,
            'author' => new AuthorResource($this->mod_author),
            'sticky' => $this->sticky,
            'categories' => CategoryResource::collection($this->categories),
            'files' => $this->whenLoaded('files', [
                'archives' => $this->files,
             ])
        ];
    }


вариант 2: прописать дополнительное отношение archived_files с ограничением
Ответ написан
@drnkwtr Автор вопроса
forblitz.ru dev
Решение, которое помогло мне избавиться от лишних запросов (реализация варианта 2, представленного Дмитрием выше)
Mod::class
public function files() {
        return $this->hasMany(File::class);
    }

    public function mod_files() {
        return $this->files()->where('type', 'mod');
    }


И ModController
public function index()
    {
        $mods = Mod::with('categories')
            ->with('mod_author')
            ->with('files')
            ->with('mod_files')
            ->paginate('10');

        return ModResource::collection($mods);
    }
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@WitER
Эта проблема подробно раскрывалась аж 2 года назад - здесь, и это первая ссылка в гугле по запросу: "laravel n+1".
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы