In MongoDB, the $rand
aggregation pipeline operator returns a random float between 0 and 1.
The floating point value has up to 17 digits after the decimal point. Any trailing zeros are dropped, so the number of digits may vary.
The $rand
operator was introduced in MongoDB 4.4.2.
Example
Suppose we have a collection called cats
with the following documents:
{ "_id" : 1, "name" : "Scratch" } { "_id" : 2, "name" : "Meow" } { "_id" : 3, "name" : "Fluffy" }
We can use the $rand
operator to generate a random number for each cat:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $rand: {} }
}
}
]
)
Result:
{ "_id" : 1, "randomNumber" : 0.5593964875463812 } { "_id" : 2, "randomNumber" : 0.04357301703691149 } { "_id" : 3, "randomNumber" : 0.7556877215199272 }
The $rand
operator doesn’t accept any arguments – you simply call it by using $rand: {}
.
Also, $rand
generates a new number each time it is called. Therefore, running the above code multiple times will produce a different random number for each cat.
Just to demonstrate this, I’ll run it again and here’s the new result:
{ "_id" : 1, "randomNumber" : 0.19672627212049873 } { "_id" : 2, "randomNumber" : 0.05513133909795318 } { "_id" : 3, "randomNumber" : 0.7509841462815067 }
We can see that the random numbers are different to the ones generated in the previous example.
Random Numbers Greater than 1
As mentioned, $rand
returns a random float between 0 and 1. This is fine if we don’t mind getting a zero, followed by up to 17 random decimal places.
But what if we want a random number greater than 1?
In such cases, we can use the $multiply
operator to multiply the result of $rand
.
Example:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $multiply: [ { $rand: {} }, 10 ] }
}
}
]
)
Result:
{ "_id" : 1, "randomNumber" : 1.958938543288535 } { "_id" : 2, "randomNumber" : 4.437057321655847 } { "_id" : 3, "randomNumber" : 8.238909118372334 }
Random Integer
We might also want to do away with the fractional part. In this case, we can use an operator such as $floor
to remove the decimal portion, therefore leaving an integer.
Example:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 10 ]
}
}
}
}
]
)
Result:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 0 } { "_id" : 2, "name" : "Meow", "randomNumber" : 5 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 7 }
Here it is again, but this time we multiply it by 100:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 100 ]
}
}
}
}
]
)
Result:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 18 } { "_id" : 2, "name" : "Meow", "randomNumber" : 62 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 92 }
Save the Results
As mentioned, $rand
generates a new random float each time it’s called. This is fine if we want a new random number each time we run the code, but what if we want to store the random number in each document?
To store the random number in the document, we can use the $addFields
operator (or its alias $set
) to add the new field to the document.
Example:
db.cats.aggregate(
[
{ $set: { randomNumber: { $multiply: [ { $rand: {} }, 100 ] } } },
{ $set: { randomNumber: { $floor: "$randomNumber" } } },
{ $merge: "cats" }
]
)
In this example, we separate the operation across two $set
stages and a $merge
stage.
The $merge
stage writes the results of the aggregation pipeline to a specified collection, and it must be the last stage in the pipeline.
Now when we return the documents from that collection (e.g. by using a method like find()
), we can see that each document contains the new field with the random number:
db.cats.find()
Result:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Now the random number is persistent. We can return the documents as many times as we like, and the random number will remain the same.
Let’s run find()
again:
db.cats.find()
Result:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Exactly the same random number.