En utilisant Map / Reduce, vous pouvez certainement obtenir un enregistrement aléatoire, mais pas nécessairement très efficacement en fonction de la taille de la collection filtrée résultante avec laquelle vous finissez par travailler.
J'ai testé cette méthode avec 50000 documents (le filtre la réduit à environ 30000), et elle s'exécute en environ 400 ms sur un Intel i3 avec 16 Go de RAM et un disque dur SATA3 ...
db.toc_content.mapReduce(
/* map function */
function() { emit( 1, this._id ); },
/* reduce function */
function(k,v) {
var r = Math.floor((Math.random()*v.length));
return v[r];
},
/* options */
{
out: { inline: 1 },
/* Filter the collection to "A"ctive documents */
query: { status: "A" }
}
);
La fonction Carte crée simplement un tableau des identifiants de tous les documents qui correspondent à la requête. Dans mon cas, j'ai testé cela avec environ 30 000 des 50 000 documents possibles.
La fonction Reduce choisit simplement un entier aléatoire entre 0 et le nombre d'éléments (-1) dans le tableau, puis renvoie cet _id dans le tableau.
400 ms sonne comme une longue période, et c'est vraiment le cas, si vous aviez cinquante millions d'enregistrements au lieu de cinquante mille, cela peut augmenter les frais généraux au point où ils deviennent inutilisables dans des situations multi-utilisateurs.
Il existe un problème ouvert pour MongoDB d'inclure cette fonctionnalité dans le noyau ... https://jira.mongodb.org/browse/SERVER-533
Si cette sélection "aléatoire" était intégrée dans une recherche d'index au lieu de collecter des identifiants dans un tableau, puis d'en sélectionner un, cela aiderait incroyablement. (allez voter!)