Usando Map / Reduce, ciertamente puede obtener un registro aleatorio, pero no necesariamente de manera muy eficiente dependiendo del tamaño de la colección filtrada resultante con la que termina trabajando.
He probado este método con 50,000 documentos (el filtro lo reduce a aproximadamente 30,000), y se ejecuta en aproximadamente 400 ms en un Intel i3 con 16 GB de RAM y un HDD 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 función de mapa simplemente crea una matriz de id de todos los documentos que coinciden con la consulta. En mi caso, probé esto con aproximadamente 30,000 de los 50,000 documentos posibles.
La función Reducir simplemente elige un número entero aleatorio entre 0 y el número de elementos (-1) en la matriz, y luego devuelve ese _id de la matriz.
400 ms parece mucho tiempo, y realmente lo es, si tuviera cincuenta millones de registros en lugar de cincuenta mil, esto puede aumentar la sobrecarga hasta el punto en que se vuelva inutilizable en situaciones de múltiples usuarios.
Hay un problema abierto para que MongoDB incluya esta característica en el núcleo ... https://jira.mongodb.org/browse/SERVER-533
Si esta selección "aleatoria" se integrara en una búsqueda de índice en lugar de recopilar identificadores en una matriz y luego seleccionar uno, esto sería de gran ayuda. (¡Ve a votar!)