Ce fut il y a répondu depuis longtemps et, depuis lors, MongoDB a beaucoup évolué.
Comme posté dans une autre réponse, MongoDB prend désormais en charge sampling within the Aggregation Framework depuis la version 3.2:
La façon dont vous pouvez faire est:
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 some warnings à propos de l'opérateur d'échantillonnage $:
(comme f nov 6 h 2017, où la plus récente version 3.4) => Si tout cela n'est pas remplie:
- échantillon $ est la première étape du pipeline
- N est inférieur à 5% des documents au total dans la collection
- la collection contient plus de 100 documents
Si l'une des conditions ci-dessus ne sont pas remplies, $ exemple effectue un suivi scan collection par un tri aléatoire pour sélectionner les documents N.
Comme dans le dernier exemple avec le match de $
VIEUX ANSWER
Vous pouvez toujours courir:
db.products.find({category:"Electronic Devices"}).skip(Math.random()*YOUR_COLLECTION_SIZE)
Mais l'ordre ne sera pas aléatoire et vous besoin de deux requêtes (un compte pour obtenir YOUR_COLLECTION_SIZE) ou d'estimer combien il est gros (il s'agit d'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 numéro. L'inconvénient ici serait que vous obtiendrez les mêmes résultats chaque fois que vous exécutez la même requête. Pour résoudre ce problème, vous pouvez toujours jouer avec la limite et sauter ou même avec le tri. vous pourriez aussi bien 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 votre, disons, fiche produit ressemblerait à ceci:
{
_id: ObjectId("..."),
name: "Awesome Product",
category: "Electronic Devices",
}
et je suggère d'utiliser:
{
_id: ObjectId("..."),
name: "Awesome Product",
category: "Electronic Devices",
_random_sample: Math.random()
}
Ensuite, vous pouvez 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 tout simplement à chaque fois que vous récupérez des enregistrements que vous pouvez mettre à jour tous ou quelques-uns (selon le nombre de dossiers que vous avez récupéré)
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);
}
EDIT
Be conscient que
db.products.update(your_query,{$set:{_random_sample::Math.random()}},false,true)
ne fonctionnera pas très bien car il mettra à jour chaque pro conduits qui correspond à votre requête avec le même nombre aléatoire. La dernière approche fonctionne mieux (mise à jour des documents que vous les récupérer)
Est-ce vraiment seulement 10 documents de 100? Si oui, alors pourquoi optimiser si la solution actuelle fonctionne? – Prinzhorn
Eh bien, ce n'est qu'un exemple, je m'attends à ce que la collection se développe en 1000s – Iladarsda