È possibile dare una prova - è veloce, lavora con documenti multipli e non richiede popolando rand
campo all'inizio, che alla fine popolarsi:
- aggiungere indice .rand campo sul vostro raccolta
- utilizzo trovare e aggiornare, qualcosa come:
// 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)
}
})
fonte
2014-11-19 22:47:26
C'è una [richiesta di funzionalità per ottenere elementi casuali da una raccolta] (https://jira.mongodb.org/browse/SERVER-533) nel Ticket tracker MongoDB. Se implementato in modo nativo, sarebbe probabilmente l'opzione più efficiente. (Se vuoi la funzione, vai a votare.) –
Questa domanda è stata posta sotto molte forme qui su Stack Overflow. La domanda più popolare è [Record casuale da MongoDB] (http://stackoverflow.com/questions/2824157/random-record-from-mongodb) - ha buone risposte. Detto questo, penso che il modo migliore di pensare alla domanda sia non pensare di ottenere un documento a caso ma, piuttosto, randomizzare un set di risultati, proprio come hai chiesto tu! Vedi [Ordinando un set di risultati a caso in Mongo] (http://stackoverflow.com/questions/8500266/ordering-a-result-set-randomly-in-mongo) per quello. –