La recette suivante est un peu plus lente que la solution mongo cookbook (ajouter une clé aléatoire sur chaque document), mais renvoie des documents aléatoires plus uniformément distribués. La distribution est un peu moins régulière que celle de la solution skip( random )
mais beaucoup plus rapide et plus sûre en cas de suppression de documents.
function draw(collection, query) {
// query: mongodb query object (optional)
var query = query || { };
query['random'] = { $lte: Math.random() };
var cur = collection.find(query).sort({ rand: -1 });
if (! cur.hasNext()) {
delete query.random;
cur = collection.find(query).sort({ rand: -1 });
}
var doc = cur.next();
doc.random = Math.random();
collection.update({ _id: doc._id }, doc);
return doc;
}
Il vous demande également d'ajouter un champ "aléatoire" à vos documents, n'oubliez pas de l'ajouter lorsque vous les créez : vous devrez peut-être initialiser votre collection comme indiqué par Geoffrey.
function addRandom(collection) {
collection.find().forEach(function (obj) {
obj.random = Math.random();
collection.save(obj);
});
}
db.eval(addRandom, db.things);
Résultats de l'évaluation comparative
Cette méthode est beaucoup plus rapide que la méthode skip()
(de ceejayoz) et génère des documents plus uniformément aléatoires que la méthode "cookbook" rapportée par Michael :
Pour une collection de 1.000.000 d'éléments :
Avec la méthode du livre de cuisine, un grand nombre de documents ne seront jamais sélectionnés parce que leur numéro aléatoire ne les favorise pas.
-
Cette méthode permet de prélever tous les éléments de manière uniforme au fil du temps.
-
Dans mon évaluation, elle n'était que 30 % plus lente que la méthode du livre de recettes.
-
le caractère aléatoire n'est pas parfait à 100% mais il est très bon (et il peut être amélioré si nécessaire)
Cette recette n'est pas parfaite - la solution idéale serait une fonction intégrée, comme d'autres l'ont fait remarquer.
Cependant, il devrait constituer un bon compromis pour de nombreux usages.
2 votes
Voir aussi SO question intitulée "Ordonner un ensemble de résultats de façon aléatoire dans mongo". . La réflexion sur le classement aléatoire d'un ensemble de résultats est une version plus générale de cette question, plus puissante et plus utile.
14 votes
Cette question revient sans cesse. Les dernières informations peuvent probablement être trouvées sur le site demande de fonctionnalité pour obtenir des éléments aléatoires d'une collection dans le ticket tracker de MongoDB. Si elle était implémentée en mode natif, ce serait probablement l'option la plus efficace. (Si vous voulez cette fonctionnalité, allez voter pour elle).
0 votes
Est-ce une collection sharded ?
4 votes
La réponse correcte a été donnée par @JohnnyHK ci-dessous : db.mycoll.aggregate( { $sample : { size : 1 } } )
0 votes
Quelqu'un sait-il combien cela est plus lent que de prendre simplement le premier disque ? Je me demande si cela vaut la peine de prendre un échantillon aléatoire pour faire quelque chose plutôt que de le faire dans l'ordre.
1 votes
En fait, l'opposé des réponses $sample n'est peut-être pas la solution la plus rapide. En effet, mongo peut effectuer un balayage de la collection pour un tri aléatoire lors de l'utilisation de $sample en fonction de la situation. Veuillez consulter : Référence : docs.mongodb.com/manuel/référence/opérateur/agrégation/sample Peut-être qu'en comptant l'ensemble des résultats et en effectuant quelques prises aléatoires, on obtiendra de meilleurs résultats.