W MongoDB $rand
Operator potoku agregacji zwraca losową liczbę zmiennoprzecinkową z zakresu od 0 do 1.
Wartość zmiennoprzecinkowa ma do 17 cyfr po przecinku. Wszelkie końcowe zera są usuwane, więc liczba cyfr może się różnić.
$rand
operator został wprowadzony w MongoDB 4.4.2.
Przykład
Załóżmy, że mamy kolekcję o nazwie cats
z następującymi dokumentami:
{ "_id" : 1, "name" : "Scratch" } { "_id" : 2, "name" : "Meow" } { "_id" : 3, "name" : "Fluffy" }
Możemy użyć $rand
operator do wygenerowania losowej liczby dla każdego kota:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $rand: {} }
}
}
]
)
Wynik:
{ "_id" : 1, "randomNumber" : 0.5593964875463812 } { "_id" : 2, "randomNumber" : 0.04357301703691149 } { "_id" : 3, "randomNumber" : 0.7556877215199272 }
$rand
operator nie przyjmuje żadnych argumentów – po prostu wywołujesz go za pomocą $rand: {}
.
Również $rand
generuje nowy numer przy każdym wywołaniu. Dlatego wielokrotne uruchomienie powyższego kodu spowoduje wygenerowanie innej liczby losowej dla każdego kota.
Aby to zademonstrować, uruchomię go ponownie i oto nowy wynik:
{ "_id" : 1, "randomNumber" : 0.19672627212049873 } { "_id" : 2, "randomNumber" : 0.05513133909795318 } { "_id" : 3, "randomNumber" : 0.7509841462815067 }
Widzimy, że liczby losowe różnią się od tych wygenerowanych w poprzednim przykładzie.
Liczby losowe większe niż 1
Jak wspomniano, $rand
zwraca losową liczbę zmiennoprzecinkową między 0 a 1. Jest to w porządku, jeśli nie mamy nic przeciwko uzyskaniu zera, po którym następuje do 17 losowych miejsc po przecinku.
Ale co, jeśli chcemy losowej liczby większej niż 1?
W takich przypadkach możemy użyć $multiply
operator do pomnożenia wyniku $rand
.
Przykład:
db.cats.aggregate(
[
{
$project:
{
randomNumber: { $multiply: [ { $rand: {} }, 10 ] }
}
}
]
)
Wynik:
{ "_id" : 1, "randomNumber" : 1.958938543288535 } { "_id" : 2, "randomNumber" : 4.437057321655847 } { "_id" : 3, "randomNumber" : 8.238909118372334 }
Losowa liczba całkowita
Możemy również chcieć pozbyć się części ułamkowej. W tym przypadku możemy użyć operatora takiego jak $floor
aby usunąć część dziesiętną, pozostawiając liczbę całkowitą.
Przykład:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 10 ]
}
}
}
}
]
)
Wynik:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 0 } { "_id" : 2, "name" : "Meow", "randomNumber" : 5 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 7 }
I znowu, ale tym razem mnożymy to przez 100:
db.cats.aggregate(
[
{
$project:
{
name: 1,
randomNumber: {
$floor: {
$multiply: [ { $rand: {} }, 100 ]
}
}
}
}
]
)
Wynik:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 18 } { "_id" : 2, "name" : "Meow", "randomNumber" : 62 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 92 }
Zapisz wyniki
Jak wspomniano, $rand
generuje nowy losowy zmiennoprzecinkowy przy każdym wywołaniu. Jest to w porządku, jeśli chcemy uzyskać nową liczbę losową za każdym razem, gdy uruchamiamy kod, ale co, jeśli chcemy przechowywać liczbę losową w każdym dokumencie?
Aby zapisać losową liczbę w dokumencie, możemy użyć $addFields
operator (lub jego alias $set
), aby dodać nowe pole do dokumentu.
Przykład:
db.cats.aggregate(
[
{ $set: { randomNumber: { $multiply: [ { $rand: {} }, 100 ] } } },
{ $set: { randomNumber: { $floor: "$randomNumber" } } },
{ $merge: "cats" }
]
)
W tym przykładzie dzielimy operację na dwa $set
etapy i $merge
scena.
$merge
stage zapisuje wyniki potoku agregacji do określonej kolekcji i musi to być ostatni etap potoku.
Teraz, gdy zwracamy dokumenty z tej kolekcji (np. za pomocą metody takiej jak find()
), widzimy, że każdy dokument zawiera nowe pole z losową liczbą:
db.cats.find()
Wynik:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Teraz liczba losowa jest trwała. Możemy zwracać dokumenty tyle razy, ile chcemy, a liczba losowa pozostanie taka sama.
Uruchommy find()
ponownie:
db.cats.find()
Wynik:
{ "_id" : 1, "name" : "Scratch", "randomNumber" : 61 } { "_id" : 2, "name" : "Meow", "randomNumber" : 86 } { "_id" : 3, "name" : "Fluffy", "randomNumber" : 73 }
Dokładnie ta sama liczba losowa.