In MongoDB, il $rand
l'operatore della pipeline di aggregazione restituisce un float casuale compreso tra 0 e 1.
Il valore in virgola mobile ha fino a 17 cifre dopo la virgola decimale. Eventuali zeri finali vengono eliminati, quindi il numero di cifre può variare.
Il $rand
operatore è stato introdotto in MongoDB 4.4.2.
Esempio
Supponiamo di avere una collezione chiamata cats
con i seguenti documenti:
{ "_id" : 1, "name" : "Scratch" } { "_id" : 2, "name" : "Meow" } { "_id" : 3, "name" : "Fluffy" }
Possiamo usare il $rand
operatore per generare un numero casuale per ogni gatto:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $rand: {} }
}
}
]
)
Risultato:
{ "_id" : 1, "randomNumber" : 0.5593964875463812 } { "_id" : 2, "randomNumber" : 0.04357301703691149 } { "_id" : 3, "randomNumber" : 0.7556877215199272 }
Il $rand
l'operatore non accetta alcun argomento:lo chiami semplicemente usando $rand: {}
.
Inoltre, $rand
genera un nuovo numero ogni volta che viene chiamato. Pertanto, l'esecuzione del codice sopra più volte produrrà un numero casuale diverso per ogni cat.
Solo per dimostrarlo, lo eseguirò di nuovo ed ecco il nuovo risultato:
{ "_id" : 1, "randomNumber" : 0.19672627212049873 } { "_id" : 2, "randomNumber" : 0.05513133909795318 } { "_id" : 3, "randomNumber" : 0.7509841462815067 }
Possiamo vedere che i numeri casuali sono diversi da quelli generati nell'esempio precedente.
Numeri casuali maggiori di 1
Come accennato, $rand
restituisce un float casuale compreso tra 0 e 1. Questo va bene se non ci dispiace ottenere uno zero, seguito da un massimo di 17 cifre decimali casuali.
Ma cosa succede se vogliamo un numero casuale maggiore di 1?
In questi casi, possiamo usare il $multiply
operatore per moltiplicare il risultato di $rand
.
Esempio:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $multiply: [ { $rand: {} }, 10 ] }
}
}
]
)
Risultato:
{ "_id" : 1, "randomNumber" : 1.958938543288535 } { "_id" : 2, "randomNumber" : 4.437057321655847 } { "_id" : 3, "randomNumber" : 8.238909118372334 }
Intero casuale
Potremmo anche voler eliminare la parte frazionaria. In questo caso, possiamo usare un operatore come $floor
per rimuovere la parte decimale, lasciando quindi un intero.
Esempio:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 10 ]
}
}
}
}
]
)
Risultato:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 0 } { "_id" : 2, "name" : "Meow", "randomNumber" : 5 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 7 }
Eccolo di nuovo, ma questa volta lo moltiplichiamo per 100:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 100 ]
}
}
}
}
]
)
Risultato:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 18 } { "_id" : 2, "name" : "Meow", "randomNumber" : 62 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 92 }
Salva i risultati
Come accennato, $rand
genera un nuovo float casuale ogni volta che viene chiamato. Questo va bene se vogliamo un nuovo numero casuale ogni volta che eseguiamo il codice, ma cosa succede se vogliamo memorizzare il numero casuale in ogni documento?
Per memorizzare il numero casuale nel documento, possiamo usare il $addFields
operatore (o il suo alias $set
) per aggiungere il nuovo campo al documento.
Esempio:
db.cats.aggregate(
[
{ $set: { randomNumber: { $multiply: [ { $rand: {} }, 100 ] } } },
{ $set: { randomNumber: { $floor: "$randomNumber" } } },
{ $merge: "cats" }
]
)
In questo esempio, separiamo l'operazione su due $set
fasi e un $merge
fase.
Il $merge
stage scrive i risultati della pipeline di aggregazione in una raccolta specificata e deve essere l'ultima fase della pipeline.
Ora, quando restituiamo i documenti da quella raccolta (ad esempio utilizzando un metodo come find()
), possiamo vedere che ogni documento contiene il nuovo campo con il numero casuale:
db.cats.find()
Risultato:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Ora il numero casuale è persistente. Possiamo restituire i documenti tutte le volte che vogliamo e il numero casuale rimarrà lo stesso.
Eseguiamo find()
ancora:
db.cats.find()
Risultato:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Esattamente lo stesso numero casuale.