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

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

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


当前回答

如果您使用的是mongoid(文档到对象的包装器),您可以执行以下操作 Ruby。(假设你的模型是User)

User.all.to_a[rand(User.count)]

在我的。irbrc,我有

def rando klass
    klass.all.to_a[rand(klass.count)]
end

所以在rails控制台,我可以做,例如,

rando User
rando Article

从任何集合中随机获取文件。

其他回答

下面的聚合操作从集合中随机选择3个文档:

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

https://docs.mongodb.com/manual/reference/operator/aggregation/sample/

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

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

您还可以使用MongoDB的地理空间索引功能来选择与随机数“最近”的文档。

首先,在集合上启用地理空间索引:

db.docs.ensureIndex( { random_point: '2d' } )

用x轴上的随机点创建一堆文档:

for ( i = 0; i < 10; ++i ) {
    db.docs.insert( { key: i, random_point: [Math.random(), 0] } );
}

然后你可以像这样从集合中随机获得一个文档:

db.docs.findOne( { random_point : { $near : [Math.random(), 0] } } )

或者你可以检索几个文档最近的随机点:

db.docs.find( { random_point : { $near : [Math.random(), 0] } } ).limit( 4 )

这只需要一个查询,没有空检查,加上代码干净,简单和灵活。您甚至可以使用地理点的y轴为查询添加第二个随机性维度。

有效可靠的方法是:

在每个文档中添加一个名为“random”的字段,并为其分配一个随机值,为该随机字段添加一个索引,如下所示:

让我们假设我们有一个名为“links”的网络链接集合,我们想从它中随机链接:

link = db.links.find().sort({random: 1}).limit(1)[0]

为了确保同一个链接不会第二次弹出,用一个新的随机数更新它的随机场:

db.links.update({random: Math.random()}, link)

如果没有数据,这是很困难的。_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);