我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
当前回答
我建议使用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)是要检索的文档数量。
这种方法可能会在分片数据库上产生一些问题。
其他回答
有效可靠的方法是:
在每个文档中添加一个名为“random”的字段,并为其分配一个随机值,为该随机字段添加一个索引,如下所示:
让我们假设我们有一个名为“links”的网络链接集合,我们想从它中随机链接:
link = db.links.find().sort({random: 1}).limit(1)[0]
为了确保同一个链接不会第二次弹出,用一个新的随机数更新它的随机场:
db.links.update({random: Math.random()}, link)
我对php的解决方案:
/**
* Get random docs from Mongo
* @param $collection
* @param $where
* @param $fields
* @param $limit
* @author happy-code
* @url happy-code.com
*/
private function _mongodb_get_random (MongoCollection $collection, $where = array(), $fields = array(), $limit = false) {
// Total docs
$count = $collection->find($where, $fields)->count();
if (!$limit) {
// Get all docs
$limit = $count;
}
$data = array();
for( $i = 0; $i < $limit; $i++ ) {
// Skip documents
$skip = rand(0, ($count-1) );
if ($skip !== 0) {
$doc = $collection->find($where, $fields)->skip($skip)->limit(1)->getNext();
} else {
$doc = $collection->find($where, $fields)->limit(1)->getNext();
}
if (is_array($doc)) {
// Catch document
$data[ $doc['_id']->{'$id'} ] = $doc;
// Ignore current document when making the next iteration
$where['_id']['$nin'][] = $doc['_id'];
}
// Every iteration catch document and decrease in the total number of document
$count--;
}
return $data;
}
在Python中使用pymongo:
import random
def get_random_doc():
count = collection.count()
return collection.find()[random.randrange(count)]
对所有记录进行计数,生成一个0到计数之间的随机数,然后执行:
db.yourCollection.find().limit(-1).skip(yourRandomNumber).next()
您还可以在执行查询后使用shuffle-array
Var shuffle = require('shuffle-array');
Accounts.find (qry函数(呃,results_array) { newIndexArr = shuffle (results_array);