我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
当前回答
现在可以使用聚合了。 例子:
db.users.aggregate(
[ { $sample: { size: 3 } } ]
)
去看医生。
其他回答
对所有记录进行计数,生成一个0到计数之间的随机数,然后执行:
db.yourCollection.find().limit(-1).skip(yourRandomNumber).next()
MongoDB现在有$rand
要选择n个非重复项,请使用{$addFields: {_f: {$rand:{}}}}进行聚合,然后按_f进行$sort和$limit n。
我建议使用map/reduce,其中使用map函数只在随机值高于给定概率时发出。
function mapf() {
if(Math.random() <= probability) {
emit(1, this);
}
}
function reducef(key,values) {
return {"documents": values};
}
res = db.questions.mapReduce(mapf, reducef, {"out": {"inline": 1}, "scope": { "probability": 0.5}});
printjson(res.results);
上面的reducef函数可以工作,因为map函数只发出一个键('1')。
“probability”的值在“scope”中定义,当调用mapRreduce(…)
像这样使用mapReduce在分片数据库上也可以使用。
如果你想从db中选择n (m)个文档,你可以这样做:
function mapf() {
if(countSubset == 0) return;
var prob = countSubset / countTotal;
if(Math.random() <= prob) {
emit(1, {"documents": [this]});
countSubset--;
}
countTotal--;
}
function reducef(key,values) {
var newArray = new Array();
for(var i=0; i < values.length; i++) {
newArray = newArray.concat(values[i].documents);
}
return {"documents": newArray};
}
res = db.questions.mapReduce(mapf, reducef, {"out": {"inline": 1}, "scope": {"countTotal": 4, "countSubset": 2}})
printjson(res.results);
其中“countTotal”(m)是数据库中的文档数量,“count子集”(n)是要检索的文档数量。
这种方法可能会在分片数据库上产生一些问题。
如果没有数据,这是很困难的。_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);
您还可以在执行查询后使用shuffle-array
Var shuffle = require('shuffle-array');
Accounts.find (qry函数(呃,results_array) { newIndexArr = shuffle (results_array);