Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.2] Add random() function to query builder #13642

Merged
merged 5 commits into from
May 25, 2016
Merged

Conversation

hamedmehryar
Copy link
Contributor

This function adds sql statements to query to get a number of random
records.

This function adds sql statements to query to get a number of random
records.
@GrahamCampbell
Copy link
Member

Does this work with all drivers?

@GrahamCampbell GrahamCampbell changed the title add random() function to query builder [5.2] Add random() function to query builder May 21, 2016
@hamedmehryar
Copy link
Contributor Author

Unfortunately no.
I'm going to implement this in different Grammars.

@hamedmehryar
Copy link
Contributor Author

Implemented in Grammars.

@GrahamCampbell
Copy link
Member

Thanks, but sqlite is still missing.

@hamedmehryar
Copy link
Contributor Author

I've tested this for sqlite and ... order by RANDOM() LIMIT 1; worked and returned a random row.
Only SqlServer and MySql have different implementations.

@GrahamCampbell
Copy link
Member

Ah, ok, Great.

@JayBizzle
Copy link
Contributor

JayBizzle commented May 22, 2016

In my opinion, this method should NOT do both order by rand AND also limit.

As it is possible to seed the RAND() MySQL function, i would expect this method to look like this...

public function random($seed = '')
{
    return $this->orderByRaw('RAND('.$seed.')');
}

if this was the case, i would suggest the method be named orderByRand() which would make Eloquent statments more readable i.e. Users::orderByRand()->limit(20)->get();

...or at an absolute push, it could be like this...

public function random($limit = 1, $seed = '')
{
    return $this->orderByRaw('RAND('.$seed.')')->limit($limit);
}

Not sure how this translates to other drivers though

@hamedmehryar
Copy link
Contributor Author

Thanks @JayBizzle, I will do some further research on it.

@hamedmehryar
Copy link
Contributor Author

Well, I split this function into two functions:
orderByRand($seed = '')
and
random($value = 1, $seed = '')

This Allows one to use:
$query->orderByRand() only to sort the results randomly.
or to use:
$query->random()->get() to get one or many random records the same as $collection->random()

@taylorotwell
Copy link
Member

Why not just use $collection->shuffle()?

@barryvdh
Copy link
Contributor

That's not helpful if you have many items, but only want to load a few (so combined with a limit)

@GrahamCampbell
Copy link
Member

Why not just use $collection->shuffle()?

Yeh, that won't be possible if there's millions of rows.

@taylorotwell
Copy link
Member

But it’s more feasible to return millions of rows via Eloquent?

On May 24, 2016, at 8:46 AM, Graham Campbell notifications@github.com wrote:

Why not just use $collection->shuffle()?

Yeh, that won't be possible if there's millions of rows.


You are receiving this because you commented.
Reply to this email directly or view it on GitHub #13642 (comment)

@barryvdh
Copy link
Contributor

The use-case is not to get ALL millions rows, but just X random rows from those million. With shuffle(), you would load all rows, but with random SQL, you only get the X rows (although random supposedly isn't very efficient either in MySQL either, but assume better then loading all rows in a collection)

@taylorotwell
Copy link
Member

But why would you get all million? Just use a where clause and LIMIT then call shuffle?

$query->where(‘foo’, ‘bar’)->limit(50)->get()->shuffle()?

On May 24, 2016, at 8:58 AM, Barry vd. Heuvel notifications@github.com wrote:

The use-case is not to get ALL millions rows, but just X random rows from those million. With shuffle(), you would load all rows, but with random SQL, you only get the X rows (although random supposedly isn't very efficient either in MySQL either, but assume better then loading all rows in a collection)


You are receiving this because you commented.
Reply to this email directly or view it on GitHub #13642 (comment)

@barryvdh
Copy link
Contributor

Because you would always get the same 50 results, never the next 50.

Simple example; you have a database with jokes (say 1000), and on the frontpage, you want to show a random one. So: $query->orderByRand()->first() will get a random one using SQL. $query->limit(50)->get()->shuffle()->first() would always load 50 same ones, $query->get()->shuffle()->first() would load all?

@taylorotwell
Copy link
Member

Gotcha

On May 24, 2016, at 9:06 AM, Barry vd. Heuvel notifications@github.com wrote:

Because you would always get the same 50 results, never the next 50.

Simple example; you have a database with jokes (say 1000), and on the frontpage, you want to show a random one. So: $query->orderByRand()->first() will get a random one using SQL. $query->limit(50)->get()->shuffle()->first() would always load 50 same ones, $query->get()->shuffle()->first() would load all?


You are receiving this because you commented.
Reply to this email directly or view it on GitHub #13642 (comment)

@barryvdh
Copy link
Contributor

But the random() with limit() is a bit much imho, just orderByRand() would probably suffice.

@vlakoff
Copy link
Contributor

vlakoff commented May 24, 2016

Same story… #5223, #5435.

@vlakoff
Copy link
Contributor

vlakoff commented May 24, 2016

You don't have to add two methods. You can do:

->orderByRandom(); // all rows

->orderByRandom()->limit(10); // 10 random rows

Also this emphasizes all the rows are ordered before being truncated. This may be a performance issue on large databases.

@taylorotwell taylorotwell merged commit f692fc2 into laravel:5.2 May 25, 2016
@taylorotwell
Copy link
Member

taylorotwell commented May 25, 2016

Changed this to just a single method: inRandomOrder...

App\User::inRandomOrder()->take(10)->get();

@barryvdh
Copy link
Contributor

Isn't orderByRandom() (or orderRandom()) more clear, that it's actually a ORDER BY statement? (In case there are multiple etc)

@JayBizzle
Copy link
Contributor

Agree with @barryvdh

Also reads better IMO

@taylorotwell
Copy link
Member

If someone asked me "how should I sort X?" I would respond with "in random order".

@KennedyTedesco
Copy link
Contributor

KennedyTedesco commented May 25, 2016

To me, orderByRand() (I prefer) or orderByRandom() it's a bit more clear, since we already have a orderBy() method.

@athahersirnaik
Copy link

Yes, orderByRandom() is bit clear

@taylorotwell
Copy link
Member

I’m not changing it. Sorry. :/

On May 25, 2016, at 8:42 AM, Athaher Sirnaik notifications@github.com wrote:

Yes, orderByRandom() is bit clear


You are receiving this because you modified the open/close state.
Reply to this email directly or view it on GitHub #13642 (comment)

@neowill2013
Copy link

orderByRandom would be better

@taylorotwell
Copy link
Member

Sorry locking this because I'm not going to be spammed all day on my inbox.

@laravel laravel locked and limited conversation to collaborators May 25, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants