MongoDB
 sql >> Base de données >  >> NoSQL >> MongoDB

MongoDB :comment trouver 10 documents au hasard dans une collection de 100 ?

Cela a été répondu il y a longtemps et, depuis lors, MongoDB a beaucoup évolué.

Comme indiqué dans une autre réponse, MongoDB prend désormais en charge l'échantillonnage dans le cadre d'agrégation depuis la version 3.2 :

Voici comment procéder :

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

Ou :

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

Cependant, il y a quelques avertissements concernant l'opérateur $sample :

(au 6 novembre 2017, où la dernière version est la 3.4) => Si l'une de ces conditions n'est pas remplie :

  • $sample est la première étape du pipeline
  • N représente moins de 5 % du total des documents de la collection
  • La collection contient plus de 100 documents

Si l'une des conditions ci-dessus n'est PAS remplie, $sample effectue une analyse de collection suivie d'un tri aléatoire pour sélectionner N documents.

Comme dans le dernier exemple avec le $match

ANCIENNE RÉPONSE

Vous pouvez toujours exécuter :

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

Mais la commande ne sera pas aléatoire et vous aurez besoin de deux requêtes (une compte pour obtenir YOUR_COLLECTION_SIZE) ou d'estimer sa taille (c'est environ 100 enregistrements, environ 1000, environ 10000...)

Vous pouvez également ajouter un champ à tous les documents avec un nombre aléatoire et interroger par ce nombre. L'inconvénient ici serait que vous obtiendrez les mêmes résultats à chaque fois que vous exécuterez la même requête. Pour résoudre ce problème, vous pouvez toujours jouer avec limit and skip ou même avec sort. vous pouvez également mettre à jour ces nombres aléatoires chaque fois que vous récupérez un enregistrement (implique plus de requêtes).

--Je ne sais pas si vous utilisez Mongoose, Mondoid ou directement le pilote Mongo pour une langue spécifique, donc je vais tout écrire sur mongo shell.

Ainsi, disons, votre enregistrement de produit ressemblerait à ceci :

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

et je suggérerais d'utiliser :

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

Ensuite, vous pourriez faire :

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

ensuite, vous pouvez exécuter périodiquement afin de mettre à jour périodiquement le champ _random_sample du document :

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)

ou juste à chaque fois que vous récupérez certains enregistrements, vous pouvez tous les mettre à jour ou seulement quelques-uns (selon le nombre d'enregistrements que vous avez récupérés)

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);
}

MODIFIER

Sachez que

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

ne fonctionnera pas très bien car il mettra à jour tous les produits qui correspondent à votre requête avec le même nombre aléatoire. La dernière approche fonctionne mieux (mise à jour de certains documents au fur et à mesure que vous les récupérez)