我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
我想从一个巨大的集合(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
从任何集合中随机获取文件。
其他回答
对所有记录进行计数,生成一个0到计数之间的随机数,然后执行:
db.yourCollection.find().limit(-1).skip(yourRandomNumber).next()
使用Python (pymongo),聚合函数也可以工作。
collection.aggregate([{'$sample': {'size': sample_size }}])
这种方法比对随机数(例如collection.find([random_int]))运行查询要快得多。对于大型收藏来说尤其如此。
您可以选择一个随机时间戳,然后搜索随后创建的第一个对象。 它将只扫描单个文档,尽管它不一定会给您一个统一的分布。
var randRec = function() {
// replace with your collection
var coll = db.collection
// get unixtime of first and last record
var min = coll.find().sort({_id: 1}).limit(1)[0]._id.getTimestamp() - 0;
var max = coll.find().sort({_id: -1}).limit(1)[0]._id.getTimestamp() - 0;
// allow to pass additional query params
return function(query) {
if (typeof query === 'undefined') query = {}
var randTime = Math.round(Math.random() * (max - min)) + min;
var hexSeconds = Math.floor(randTime / 1000).toString(16);
var id = ObjectId(hexSeconds + "0000000000000000");
query._id = {$gte: id}
return coll.find(query).limit(1)
};
}();
现在可以使用聚合了。 例子:
db.users.aggregate(
[ { $sample: { size: 3 } } ]
)
去看医生。
您还可以使用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轴为查询添加第二个随机性维度。