Используя Map / Reduce, вы, безусловно, можете получить случайную запись, но не обязательно очень эффективно, в зависимости от размера результирующей отфильтрованной коллекции, с которой вы в итоге работаете.
Я протестировал этот метод с 50 000 документов (фильтр сокращает его примерно до 30 000), и он выполняется примерно за 400 мс на Intel i3 с 16 ГБ ОЗУ и жестким диском 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" }
}
);
Функция Map просто создает массив идентификаторов всех документов, соответствующих запросу. В моем случае я проверил это примерно с 30 000 из 50 000 возможных документов.
Функция Reduce просто выбирает случайное целое число от 0 до количества элементов (-1) в массиве, а затем возвращает _id из массива.
400 мс звучит как долгое время, и действительно, если у вас пятьдесят миллионов записей вместо пятидесяти тысяч, это может увеличить накладные расходы до такой степени, что они станут непригодными для использования в многопользовательских ситуациях.
Существует открытая проблема для MongoDB по включению этой функции в ядро ... https://jira.mongodb.org/browse/SERVER-533
Если бы этот «случайный» выбор был встроен в поиск по индексу вместо того, чтобы собирать идентификаторы в массив и затем выбирать один, это невероятно помогло бы. (иди голосуй!)