Puede probar esto - es rápido, trabaja con varios documentos y no requiere poblar rand
campo al comienzo, que con el tiempo se rellenará en sí:
- agregar índice a .rand campo en su colección
- utilización encontrar y refrescar, algo así como:
// Install packages:
// npm install mongodb async
// Add index in mongo:
// db.ensureIndex('mycollection', { rand: 1 })
var mongodb = require('mongodb')
var async = require('async')
// Find n random documents by using "rand" field.
function findAndRefreshRand (collection, n, fields, done) {
var result = []
var rand = Math.random()
// Append documents to the result based on criteria and options, if options.limit is 0 skip the call.
var appender = function (criteria, options, done) {
return function (done) {
if (options.limit > 0) {
collection.find(criteria, fields, options).toArray(
function (err, docs) {
if (!err && Array.isArray(docs)) {
Array.prototype.push.apply(result, docs)
}
done(err)
}
)
} else {
async.nextTick(done)
}
}
}
async.series([
// Fetch docs with unitialized .rand.
// NOTE: You can comment out this step if all docs have initialized .rand = Math.random()
appender({ rand: { $exists: false } }, { limit: n - result.length }),
// Fetch on one side of random number.
appender({ rand: { $gte: rand } }, { sort: { rand: 1 }, limit: n - result.length }),
// Continue fetch on the other side.
appender({ rand: { $lt: rand } }, { sort: { rand: -1 }, limit: n - result.length }),
// Refresh fetched docs, if any.
function (done) {
if (result.length > 0) {
var batch = collection.initializeUnorderedBulkOp({ w: 0 })
for (var i = 0; i < result.length; ++i) {
batch.find({ _id: result[i]._id }).updateOne({ rand: Math.random() })
}
batch.execute(done)
} else {
async.nextTick(done)
}
}
], function (err) {
done(err, result)
})
}
// Example usage
mongodb.MongoClient.connect('mongodb://localhost:27017/core-development', function (err, db) {
if (!err) {
findAndRefreshRand(db.collection('profiles'), 1024, { _id: true, rand: true }, function (err, result) {
if (!err) {
console.log(result)
} else {
console.error(err)
}
db.close()
})
} else {
console.error(err)
}
})
Hay una [solicitud de función para obtener elementos aleatorios de una colección] (https://jira.mongodb.org/browse/SERVER-533) en el registrador de boletos MongoDB. Si se implementa de forma nativa, probablemente sea la opción más eficiente. (Si desea la función, vaya a votarla). –
Esta pregunta se ha formulado de muchas formas aquí en Stack Overflow. La pregunta más popular es [Registro aleatorio de MongoDB] (http://stackoverflow.com/questions/2824157/random-record-from-mongodb) - tiene buenas respuestas. Dicho esto, creo que la mejor manera de pensar sobre la cuestión es no pensar en obtener un documento aleatorio sino, más bien, aleatorizar un conjunto de resultados, ¡tal como lo pidió! Ver [Ordenar un conjunto de resultados aleatoriamente en Mongo] (http://stackoverflow.com/questions/8500266/ordering-a-result-set-randomly-in-mongo) para eso. –