Laravel Lazy Collection - Operacja na dużych zbiorach

calendar_today2020-01-20folderLaravel /  Programowanie

Mechanizm Lazy Collections, został wdrożony przez Josepha Silbera i jest to jedna z moich ulubionych nowych funkcji Laravel 6.

Dzięki zastosowaniu tego mechanizmu, możemy zoptymalizować pracę z obszernymi zbiorami danych, w tym kolekcji danych z Eloquenta. Nowa klasa "Illuminate\Support\LazyCollection" wykorzystuje generatory języka PHP by utrzymać niskie zużycie pamięci podczas pracy z ogromnymi zbiorami danych.

Dla przykładu: wyobraź sobie, że twoja aplikacja potrzebuje przetworzyć listę projektów która ma wiele gigabajtów. Używając Lazy Collection możesz przetworzyć tylko małą porcję pliku w pamięci w danym czasie.

use App\Project;
use Illuminate\Support\LazyCollection;

Route::get('/', function () {

    LazyCollection::make(function () {
        // projects.csv with 300.000 rows
        $filePath = storage_path('projects.csv');
        $handle = fopen($filePath, 'r');
        while ($line = fgetcsv($handle)) {
            yield $line;
        }
    })
        ->chunk(10000) //split in chunk to reduce the number of queries
        ->each(function ($lines) {

            $list = [];
            foreach ($lines as $line) {
                if (isset($line[1])) {
                    $list[] = [
                        'name' => $line[1],
                        'email' => $line[2],
                        'status_id' => $line[3]
                    ];
                }
            }
            // insert 10000 rows in one shot
            Project::insert($list);

        });
});

Lub musisz przeiterować 10 000 modeli Eloquenta. Używając tradycyjnych metod kolekcji wszystkie modele musiałyby zostać załadowane w tym samym czasie...

$users = App\User::all()->filter(function ($user) {
    return $user->id > 500;
});

Laravel 6 posiada metodę "cursor" w Query Buider, która wykorzystuje mechanizm Lazy Collection i zwraca instancję klasy LazyCollection. Metoda "cursor" pozwala na wykonanie pojedynczego zapytania do bazy danych i równocześnie trzymanie tylko jednego modelu Eloquenta w pamięci w danym czasie. Dla przykładu, metoda filter nie zostanie wykonana aż każdy user nie zostanie przeiterowany indywidualnie.

$users = App\User::cursor()->filter(function ($user) {
    return $user->id > 500;
});

Skontaktuj się z nami

keyboard_arrow_up