来自Mongo的随机抽样

时间:2012-09-30 20:23:03

标签: mongodb sampling database

我有一个包含文档的mongo集合。每个文档中都有一个字段为0或1.我需要从数据库中随机抽取1000条记录,并将具有该字段的文档数量计为1.我需要对此进行1000次抽样。我该怎么做?

5 个答案:

答案 0 :(得分:11)

对于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);

这为您提供了单个查找查询中的随机对象。根据您的需要,这可能有点过分,但如果您要随着时间的推移进行大量采样,这是一种非常有效的方法,而不会给您的后端带来负担。

答案 1 :(得分:10)

对于接听答案的人,您现在应该使用新的$sample聚合函数,3.2中的新功能。

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

db.collection_of_things.aggregate(
   [ { $sample: { size: 15 } } ]
)

然后使用0添加另一个步骤来计算1$group以获取计数。 Here is an example from the MongoDB docs

答案 2 :(得分:1)

以下是mongo shell中的一个示例..假设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);
    }
}

答案 3 :(得分:1)

我打算用@Stennies回复编辑我的评论,但你也可以在这里使用一个单独的自动递增ID索引作为替代,如果你要跳过大量的记录(在这里说话很多)。

我写了另一个问题的答案很像这个问题,其中有人试图找到该集合的第n条记录:

php mongodb find nth entry in collection

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

答案 4 :(得分:0)

如果您使用的是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)