2012-09-30 56 views
6

我有一个带文件的mongo集合。每个文档中有一个字段是0或1.我需要从数据库中随机抽取1000条记录,并将该字段的文档数量设为1.我需要进行1000次抽样。我该怎么做 ?Mongo随机采样

+1

您能否接受答案? –

+0

[MongoDB的随机记录]可能的重复(http://stackoverflow.com/questions/2824157/random-record-from-mongodb) –

+0

嘿Aditya,你能接受一个答案吗? – dalanmiller

回答

1

这里是在mongo壳为例..假设collname集合,并在thefield一个感兴趣的值:

var total = db.collname.count(); 
var count = 0; 
var numSamples = 1000; 

for (i = 0; i < numSamples; i++) { 
    var random = Math.floor(Math.random()*total); 
    var doc = db.collname.find().skip(random).limit(1).next(); 
    if (doc.thefield) { 
     count += (doc.thefield == 1); 
    } 
} 
+0

这也回答了另一个问题:与SQL不同,MongoDB没有真正的内置函数。此外,跳过可能(...可能)变得更大的随机值麻烦,但取决于。 – Sammaye

1

我要编辑我的@Stennies评论回答这个但你也可以如果您要跳过大量的记录(在这里说得很大),请使用分隔符自动递增ID索引作为替代。

我写了另一个回答另一个问题,很多像这样的地方有一个人正在试图找到集合的第n个记录:

php mongodb find nth entry in collection

我的答案的后半部分基本上描述了一个潜在的方法,通过你可以解决这个问题。你仍然需要循环1000次才能得到随机的排。

12

对于MongoDB 3.0和之前的版本,我使用SQL天的旧技巧(我认为维基百科用于他们的随机页面功能)。我在每个需要随机化的对象中存储一个0到1之间的随机数,我们称之为“r”。然后在“r”上添加一个索引。

db.coll.ensureIndex(r: 1); 

我们得到随机X对象,你可以使用:

var startVal = Math.random(); 
db.coll.find({r: {$gt: startVal}}).sort({r: 1}).limit(x); 

这让你在一个单一的查找查询随机对象。根据您的需要,这可能是矫枉过正的,但是如果您将要随着时间的推移进行大量抽样,这是一种非常有效的方式,不会在后端加载负载。

+0

太棒了!很聪明! –

+0

优雅的解决方案! –

-1

如果您使用的是mongoengine,则可以使用SequenceField生成增量计数器。

class User(db.DynamicDocument): 
    counter = db.SequenceField(collection_name="user.counters") 

然后获取说100的随机列表,请执行下列操作

def get_random_users(number_requested): 
    users_to_fetch = random.sample(range(1, User.objects.count() + 1), min(number_requested, User.objects.count())) 
    return User.objects(counter__in=users_to_fetch) 

,你会打电话

get_random_users(100)