我想从一个巨大的集合(1亿条记录)中获得一个随机记录。

最快最有效的方法是什么?

数据已经在那里,没有字段可以生成随机数并获得随机行。


当前回答

MongoDB现在有$rand

要选择n个非重复项,请使用{$addFields: {_f: {$rand:{}}}}进行聚合,然后按_f进行$sort和$limit n。

其他回答

为了获得确定数量的无重复的随机文档:

first get all ids get size of documents loop geting random index and skip duplicated number_of_docs=7 db.collection('preguntas').find({},{_id:1}).toArray(function(err, arr) { count=arr.length idsram=[] rans=[] while(number_of_docs!=0){ var R = Math.floor(Math.random() * count); if (rans.indexOf(R) > -1) { continue } else { ans.push(R) idsram.push(arr[R]._id) number_of_docs-- } } db.collection('preguntas').find({}).toArray(function(err1, doc1) { if (err1) { console.log(err1); return; } res.send(doc1) }); });

现在可以使用聚合了。 例子:

db.users.aggregate(
   [ { $sample: { size: 3 } } ]
)

去看医生。

对所有记录进行计数,生成一个0到计数之间的随机数,然后执行:

db.yourCollection.find().limit(-1).skip(yourRandomNumber).next()

如果没有数据,这是很困难的。_id字段是什么?它们是mongodb对象id吗?如果是这样,你可以得到最大值和最小值:

lowest = db.coll.find().sort({_id:1}).limit(1).next()._id;
highest = db.coll.find().sort({_id:-1}).limit(1).next()._id;

然后,如果你假设id是均匀分布的(但它们不是,但至少这是一个开始):

unsigned long long L = first_8_bytes_of(lowest)
unsigned long long H = first_8_bytes_of(highest)

V = (H - L) * random_from_0_to_1();
N = L + V;
oid = N concat random_4_bytes();

randomobj = db.coll.find({_id:{$gte:oid}}).limit(1);

您可以选择随机_id并返回相应的对象:

 db.collection.count( function(err, count){
        db.collection.distinct( "_id" , function( err, result) {
            if (err)
                res.send(err)
            var randomId = result[Math.floor(Math.random() * (count-1))]
            db.collection.findOne( { _id: randomId } , function( err, result) {
                if (err)
                    res.send(err)
                console.log(result)
            })
        })
    })

在这里,你不需要花空间存储随机数字的集合。