Eloquent: 5 ways to select N random records

Updated: January 16, 2024 By: Guest Contributor Post a comment

Introduction

Engaging with databases in such a way that you require randomness in results returned is a fairly common scenario in web development. When using Laravel’s Eloquent, several methods can be employed to retrieve a random set of records. Achieving this can greatly enhance user experience, particularly in situations where variety or discovery is a value proposition.

In this article, we’ll explore various methods to select N random records using Eloquent, diving into each solution in detail. Note that the term ‘records’ refers to rows or entries in your database table.

Simple Random Order

Perhaps the most straightforward approach is to use the inRandomOrder() method provided by Eloquent. It can be used in conjunction with the limit() method to retrieve a set number of records in random order:

  1. Begin by querying your model.
  2. Chain the inRandomOrder() method to introduce randomness.
  3. Use the take() method to specify the number of records N.
  4. Finally, fetch the results with get().

Example:

$randomUsers = User::inRandomOrder()->take(5)->get();

Notes: This method might not scale efficiently for very large datasets as it can be slow due to the way SQL handles sorting. For small to medium-sized tables, however, it is a slick one-liner that does the job nicely.

Random Sampling

Another technique involves randomly sampling IDs which you can later use to retrieve full records. This solution can be more efficient if the table contains a large number of rows.

  1. Fetch the IDs of all the records in the table and sample randomly.
  2. Query for full records using sampled IDs.

Example:

$sampledIDs = User::all()->modelKeys();
$randomIDs = Arr::shuffle($sampledIDs);
$randomIDs = array_slice($randomIDs, 0, 5);
$randomUsers = User::findMany($randomIDs);

Notes: While fetching all IDs still involves scanning the full table, it is much quicker than ordering the entire dataset. However, this method’s effectiveness can diminish if the table size is huge, as this would require a lot of memory.

Offset & Fetch

If you know the count of your dataset, you can implement random record retrieval by calculating an offset:

  1. Calculate the number of records in the table.
  2. Generate a random offset.
  3. Retrieve the records starting from that offset.

Example:

$count = User::count();
$offset = rand(0, $count - 5);
$randomUsers = User::offset($offset)->limit(5)->get();

Notes: This technique may not be random in the strict sense as it depends on the assumption that records are uniformly distributed. This generates a more predictable pattern, which may not be entirely desirable.

Random Where Clause

Leveraging the where clause can provide a conditionally random set of records. This method is conditional because it depends on randomness from a specific column value range:

  1. Determine a column with numeric or datable values you can randomize upon.
  2. Generate a random threshold for this column.
  3. Use a where clause to get records with column values beyond this threshold.

Example:

$randomAge = rand(18, 24);
$randomUsers = User::where('age', '>', $randomAge)->take(5)->get();

Notes: This approach is not purely random as it is contingent on the column’s distribution and will not work well on categorical or non-numeric data.

External Randomization Tool

Integrating an external randomization API or service that can help to randomly select records could be an appropriate solution for highly demanding or complex systems.

  1. Find a reliable external randomization service.
  2. Fetch record identifiers from the database.
  3. Use the service to randomize these identifiers.
  4. Query the database for the full records using the randomized IDs.

Example:

// Assuming $service->randomize() utilizes the external service
$ids = User::pluck('id')->toArray();
$randomIds = $service->randomize($ids, 5);
$randomUsers = User::findMany($randomIds);

Notes: While this method can offload the compute-intense task of randomness to another service, it introduces additional complexity, potential latency, and the need for network calls. It may also have cost implications, so it’s worth weighing against the benefits.

Conclusion

In conclusion, selecting N random records using Eloquent offers multiple paths that cater to different scenarios and database sizes. Simple methods like inRandomOrder() are excellent for quick tasks, while more intricate solutions like using external services may be required for complex circumstances or massive datasets. Understanding the impact on performance, predictability, and resource usage will guide you to pick the solution best-suited for your application.