Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get one line at a time from eloquent query in laravel?

Say I have a simple query to get all rows from a table:

App::make('My_Model')->get();

But, I have a huge number of rows - say 100,000, so many that PHP runs out of memory trying to read them all in.

For some reason I want to go through each of these rows, and do some operation based on them.

Is there any way to tell laravel to give me one row at a time, the way the old mysql_fetch_row worked?

Note: I'm currently solving this by using limit() commands to get 5000 rows at once, which works fine, except that it repeats the query 20 times.

I want to know if there is any built in method in laravel or eloquent to give me the next row, instead of all rows ?

like image 618
Benubird Avatar asked Apr 03 '14 09:04

Benubird


People also ask

Is query Builder faster than eloquent?

Eloquent ORM is best suited working with fewer data in a particular table. On the other side, query builder takes less time to handle numerous data whether in one or more tables faster than Eloquent ORM. In my case, I use ELoquent ORM in an application with tables that will hold less than 17500 entries.

What does get () do in Laravel?

This allows you to add conditions throughout your code until you actually want to fetch them, and then you would call the get() function.

What is pluck in Laravel query?

Laravel Pluck() is a Laravel Collections method used to extract certain values from the collection. You might often would want to extract certain data from the collection i.e Eloquent collection.


3 Answers

For anybody landing here using Laravel 5.2+ (like I did) There is now a 'cursor' method available which returns a Generator

https://laravel.com/api/5.2/Illuminate/Database/Query/Builder.html#method_cursor

So instead of ->get() use ->cursor()

like image 137
Matt Brown Avatar answered Sep 21 '22 16:09

Matt Brown


If you want to process them, a thousand at a time say, the chunk() method in Eloquent should work for you:

My_Model::chunk(1000, function($my_models)
{
    foreach ($my_models as $my_model)
    {
        // do something
    }
});

More in the Eloquent docs

Depends on what you are doing to your data...

like image 31
msturdy Avatar answered Sep 20 '22 16:09

msturdy


The problem is, what is the next row in an application that lives shortly? Unless you are building a command line application that has a cursor, you application lives just for a request. Laravel can give you ways to get a subset of your cursor, so if you need 5000 lines, you can get those 5000 lines at the same time.

So you can use paginate:

$someUsers = User::where('votes', '>', 100)->paginate(5000);

Take and skip:

$page = 5;

$pageSize = 5000;

$users = User::skip($page * $pageSize)->take($pageSize)->get();

Chunk, internally uses paginagion, but it's a little bit restricting, because it will force you to process your whole cursor:

User::chunk(5000, function($users)
{
    /// every time this clojure is ran you get a new subset of 5000 rows.

    foreach ($users as $user)
    {
        // do whatever you need with them
    }
});

Sidenote: you can save memory by turning query log off:

DB::disableQueryLog();
like image 26
Antonio Carlos Ribeiro Avatar answered Sep 19 '22 16:09

Antonio Carlos Ribeiro