sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB:¿cómo encontrar 10 documentos aleatorios en una colección de 100?

Esto fue respondido hace mucho tiempo y, desde entonces, MongoDB ha evolucionado mucho.

Como se publicó en otra respuesta, MongoDB ahora admite el muestreo dentro del marco de agregación desde la versión 3.2:

La forma en que podrías hacer esto es:

db.products.aggregate([{$sample: {size: 5}}]); // You want to get 5 docs

O:

db.products.aggregate([
  {$match: {category:"Electronic Devices"}}, // filter the results
  {$sample: {size: 5}} // You want to get 5 docs
]);

Sin embargo, hay algunas advertencias sobre el operador $sample:

(a partir del 6 de noviembre de 2017, donde la última versión es 3.4) => Si algo de esto no se cumple:

  • $sample es la primera etapa de la canalización
  • N es menos del 5 % del total de documentos de la colección
  • La colección contiene más de 100 documentos

Si NO se cumple ninguna de las condiciones anteriores, $sample realiza un análisis de colección seguido de una clasificación aleatoria para seleccionar N documentos.

Como en el último ejemplo con $match

RESPUESTA ANTIGUA

Siempre puedes ejecutar:

db.products.find({category:"Electronic Devices"}).skip(Math.random()*YOUR_COLLECTION_SIZE)

Pero el orden no será aleatorio y necesitarás dos consultas (un conteo para obtener TU_TAMAÑO_DE_COLECCIÓN) o estimar qué tan grande es (son alrededor de 100 registros, alrededor de 1000, alrededor de 10000...)

También puede agregar un campo a todos los documentos con un número aleatorio y consultar por ese número. El inconveniente aquí sería que obtendrá los mismos resultados cada vez que ejecute la misma consulta. Para arreglar eso, siempre puedes jugar con limit y skip o incluso con sort. también podría actualizar esos números aleatorios cada vez que obtenga un registro (implica más consultas).

--No sé si está utilizando Mongoose, Mondoid o directamente Mongo Driver para algún idioma específico, así que escribiré todo sobre mongo shell.

Por lo tanto, digamos que su registro de producto se vería así:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
}

y sugeriría usar:

{
 _id: ObjectId("..."),
 name: "Awesome Product",
 category: "Electronic Devices",
 _random_sample: Math.random()
}

Entonces podrías hacer:

db.products.find({category:"Electronic Devices",_random_sample:{$gte:Math.random()}})

luego, puede ejecutar periódicamente para actualizar el campo _random_sample del documento periódicamente:

var your_query = {} //it would impact in your performance if there are a lot of records
your_query = {category: "Electronic Devices"} //Update 
//upsert = false, multi = true
db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

o simplemente cada vez que recupere algunos registros, puede actualizarlos todos o solo algunos (dependiendo de cuántos registros haya recuperado)

for(var i = 0; i < records.length; i++){
   var query = {_id: records[i]._id};
   //upsert = false, multi = false
   db.products.update(query,{$set:{_random_sample::Math.random()}},false,false);
}

EDITAR

Tenga en cuenta que

db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)

no funcionará muy bien, ya que actualizará todos los productos que coincidan con su consulta con lo mismo número aleatorio. El último enfoque funciona mejor (actualizar algunos documentos a medida que los recupera)