Navigation

$rand (aggregation)

Definition

$rand

New in version 4.4.2.

Returns a random float between 0 and 1 each time it is called.

$rand has the following syntax:

{ $rand: {} }

The $rand operator doesn’t take any arguments.

Behavior

Each time $rand is called it will return a floating point value that has up to 17 digits after the decimal point. Trailing 0s are dropped so the actual number of digits may vary.

Examples

Generate Random Data Points

This example models charitable donations. The collection starts with a list of donors.

db.donors.insertMany(
   [
     { donorId: 1000, amount: 0, frequency: 1 },
     { donorId: 1001, amount: 0, frequency: 2 },
     { donorId: 1002, amount: 0, frequency: 1 },
     { donorId: 1003, amount: 0, frequency: 2 },
     { donorId: 1004, amount: 0, frequency: 1 }
   ]
)

We use an aggregation pipeline to update each document with a random donation amount.

db.donors.aggregate(
   [
      { $set: { amount: { $multiply: [ { $rand: {} }, 100 ] } } },
      { $set: { amount: { $floor: "$amount" } } },
      { $merge: "donors" }
   ]
)

The first $set stage updates the amount field. An initial value between 0 and 1 is generated using $rand. Then $multiply scales it upward 100 times.

The $floor operator in the second $set stage removes the decimal portion from the amount to leave an integer value.

Finally, $merge writes the random value created in the previous steps to the amount field, updating it for each document in the donors collection.

You can view the results with a projection stage:

db.donors.aggregate(
   [
      { $project: {_id: 0, donorId: 1, amount: 1 } }
   ]
)

The projection shows the scaled amounts are now random values in the range from 0 to 99.

{ "donorId" : 1000, "amount" : 27 }
{ "donorId" : 1001, "amount" : 10 }
{ "donorId" : 1002, "amount" : 88 }
{ "donorId" : 1003, "amount" : 73 }
{ "donorId" : 1004, "amount" : 5 }

Select Random Items From a Collection

You can use $rand in an aggregation pipeline to select random documents from a collection. Consider a collection of voter records:

db.voters.insertMany(
   [
     { name: "Archibald", voterId: 4321, district: 3, registered: true },
     { name: "Beckham", voterId: 4331, district: 3, registered: true },
     { name: "Carolin", voterId: 5321, district: 4, registered: true },
     { name: "Debarge", voterId: 4343, district: 3, registered: false },
     { name: "Eckhard", voterId: 4161, district: 3, registered: false },
     { name: "Faberge", voterId: 4300, district: 1, registered: true },
     { name: "Grimwald", voterId: 4111, district: 3, registered: true },
     { name: "Humphrey", voterId: 2021, district: 3, registered: true },
     { name: "Idelfon", voterId: 1021, district: 4, registered: true },
     { name: "Justo", voterId: 9891, district: 3, registered: false }
   ]
)

Imagine you want to select about half of the voters in District 3 to do some polling.

db.voters.aggregate(
   [
      { $match: { district: 3 } },
      { $match: { $expr: { $lt: [0.5, {$rand: {} } ] } } },
      { $project: { _id: 0, name: 1, registered: 1 } }
   ]
)

The first pipeline stage matches all documents where the voter is from district 3.

The second $match stage uses $rand in a match expression to further refine the selection. For each document, $rand generates a value between 0 and 1. The threshhold of 0.5 in the less than ($lt) comparison means that $expr will be true for about half the documents.

In the $project stage the selected documents are filtered to return the name and registered fields. There are 7 voters in District 3, running the code selects about half of them.

{ "name" : "Archibald", "registered" : true }
{ "name" : "Debarge", "registered" : false }
{ "name" : "Humphrey", "registered" : true }

Note

The number of documents selected is different each time. If you need to select an exact number of documents, consider using $sample instead of $rand.