No MongoDB, o
$rand
operador de pipeline de agregação retorna um float aleatório entre 0 e 1. O valor de ponto flutuante tem até 17 dígitos após o ponto decimal. Quaisquer zeros à direita são descartados, portanto, o número de dígitos pode variar.
O
$rand
O operador foi introduzido no MongoDB 4.4.2. Exemplo
Suponha que tenhamos uma coleção chamada
cats
com os seguintes documentos:{ "_id" :1, "name" :"Scratch" }{ "_id" :2, "name" :"Miau" }{ "_id" :3, "name" :"Fofo" }
Podemos usar o$rand
operador para gerar um número aleatório para cada gato:
db.cats.aggregate( [ { $project:{ randomNumber:{ $rand:{} } } } ])
Resultado:
{ "_id" :1, "randomNumber" :0.5593964875463812 }{ "_id" :2, "randomNumber" :0.04357301703691149 }{ "_id" :3, "randomNumber" :0.7556877215199272 }
O$rand
operador não aceita nenhum argumento – basta chamá-lo usando$rand:{}
.
Além disso,$rand
gera um novo número cada vez que é chamado. Portanto, executar o código acima várias vezes produzirá um número aleatório diferente para cada gato.
Apenas para demonstrar isso, vou executá-lo novamente e aqui está o novo resultado:
{ "_id" :1, "randomNumber" :0.19672627212049873 }{ "_id" :2, "randomNumber" :0.05513133909795318 }{ "_id" :3, "randomNumber" :0.7509841462815067 }
Podemos ver que os números aleatórios são diferentes dos gerados no exemplo anterior.
Números aleatórios maiores que 1
Como mencionado,$rand
retorna um float aleatório entre 0 e 1. Isso é bom se não nos importamos em obter um zero, seguido por até 17 casas decimais aleatórias.
Mas e se quisermos um número aleatório maior que 1?
Nesses casos, podemos usar o$multiply
operador para multiplicar o resultado de$rand
.
Exemplo:
db.cats.aggregate( [ { $project:{ randomNumber:{ $multiply:[ { $rand:{} }, 10 ] } } } ])
Resultado:
{ "_id" :1, "randomNumber" :1.958938543288535 }{ "_id" :2, "randomNumber" :4.437057321655847 }{ "_id" :3, "randomNumber" :8.238909118372334 }Inteiro aleatório
Também podemos querer acabar com a parte fracionária. Neste caso, podemos usar um operador como$floor
para remover a parte decimal, deixando assim um inteiro.
Exemplo:
db.cats.aggregate( [ { $project:{ name:1, randomNumber:{ $floor:{ $multiply:[ { $rand:{} }, 10 ] } } } } ])
Resultado:
{ "_id" :1, "name" :"Scratch", "randomNumber" :0 }{ "_id" :2, "name" :"Meow", "randomNumber" :5 }{ "_id" :3, "name" :"Fofo", "randomNumber" :7 }
Aqui está novamente, mas desta vez multiplicamos por 100:
db.cats.aggregate( [ { $project:{ name:1, randomNumber:{ $floor:{ $multiply:[ { $rand:{} }, 100 ] } } } } ])
Resultado:
{ "_id" :1, "name" :"Scratch", "randomNumber" :18 }{ "_id" :2, "name" :"Meow", "randomNumber" :62 }{ "_id" :3, "name" :"Fofo", "randomNumber" :92 }Salvar os resultados
Como mencionado,$rand
gera um novo float aleatório cada vez que é chamado. Isso é bom se quisermos um novo número aleatório toda vez que executarmos o código, mas e se quisermos armazenar o número aleatório em cada documento?
Para armazenar o número aleatório no documento, podemos usar o$addFields
operador (ou seu alias$set
) para adicionar o novo campo ao documento.
Exemplo:
db.cats.aggregate( [ { $set:{ randomNumber:{ $multiply:[ { $rand:{} }, 100 ] } } }, { $set:{ randomNumber:{ $floor:"$randomNumber" } } }, { $merge:"cats" } ])
Neste exemplo, separamos a operação em dois$set
estágios e um$merge
etapa.
O$merge
stage grava os resultados do pipeline de agregação em uma coleção especificada e deve ser o último estágio no pipeline.
Agora, quando retornamos os documentos dessa coleção (por exemplo, usando um método comofind()
), podemos ver que cada documento contém o novo campo com o número aleatório:
db.cats.find()
Resultado:
{ "_id" :1, "name" :"Scratch", "randomNumber" :61 }{ "_id" :2, "name" :"Meow", "randomNumber" :86 }{ "_id" :3, "name" :"Fofo", "randomNumber" :73 }
Agora o número aleatório é persistente. Podemos devolver os documentos quantas vezes quisermos, e o número aleatório permanecerá o mesmo.
Vamos executarfind()
novamente:
db.cats.find()
Resultado:
{ "_id" :1, "name" :"Scratch", "randomNumber" :61 }{ "_id" :2, "name" :"Meow", "randomNumber" :86 }{ "_id" :3, "name" :"Fofo", "randomNumber" :73 }
Exatamente o mesmo número aleatório.