如何使用python从mongoDB中的10亿个文档中获取随机单个文档?

Hit*_*try 9 python mongodb pymongo

我想要来自mongoDB集合的单个随机文档.现在我的mongoDB集合包含超过10亿个集合.如何从该集合中获取单个随机文档?

Leo*_*tny 21

我从未使用Python的MongoDB,但是有一个通用的解决方案可以解决你的问题.这是一个用于获取单个随机文档的MongoDB shell脚本:

N = db.collection.count(condition)
db.collection.find(condition).limit(1).skip(Math.floor(Math.random()*N))
Run Code Online (Sandbox Code Playgroud)

condition这是一个MongoDB查询.如果要查询整个集合,请使用query = null.

这是一个通用解决方案,因此适用于任何MongoDB驱动程序.


更新

我运行了一个基准来测试几个实现.首先,我使用带有索引随机字段的5567249文档创建了测试集合rnd.

我选择了三种方法来相互比较:

第一种方法:

db.collection.find().limit(1).skip(Math.floor(Math.random()*N))
Run Code Online (Sandbox Code Playgroud)

第二种方法:

db.collection.find({rnd: {$gte: Math.random()}}).sort({rnd:1}).limit(1)
Run Code Online (Sandbox Code Playgroud)

第三种方法:

db.collection.findOne({rnd: {$gte: Math.random()}})
Run Code Online (Sandbox Code Playgroud)

我运行了每个方法10次并得到了它的平均计算时间:

method 1: 882.1 msec
method 2: 1.2 msec
method 3: 0.6 msec
Run Code Online (Sandbox Code Playgroud)

这个基准测试显示我的解决方案不是最快的.

但第三种解决方案也不是一个好的解决方案,因为它找到了数据库中的第一个元素(按自然顺序排序)rnd > random().所以,它的输出并不是真正随机的.

我认为第二种方法是经常使用的最佳方法.但它有一个缺陷:它需要改变整个数据库并确保额外的索引.

  • 我决定运行一个基准来测试它.我会在这里发布我的结果. (5认同)

Cal*_*eng 6

添加一个名为random您的集合的附加列,并使其中的值介于0到1之间.您可以为此列中的每个记录分配0到1之间的随机浮点数[random.random() for _ in range(0, 10)].

然后:-

import random

collection = mongodb["collection_name"]

rand = random.random()  # rand will be a floating point between 0 to 1.
random_record = collection.find_one({ 'random' => { '$gte' => rand } })
Run Code Online (Sandbox Code Playgroud)

MongoDB将在适当的时候实现其原生实现.提交的功能在这里 - https://jira.mongodb.org/browse/SERVER-533

在撰写本文时尚未实施.

  • 我会不会同意的.即使它不适合所有情况,这个答案也是一个很好的通用答案.例如,维基百科将此解决方案用于其随机页面功能. (3认同)
  • 您不必修改数据即可.它甚至可能不是您的数据! (2认同)

kot*_*rfa 6

因为MongoDB 3.2,可以使用aggregate带有$sample运算符的函数来完成,如文档中所述.它超级快.以下代码将从集合中随机选择20个文档.

db.collection.aggregate( [ { $sample: {size: 20} } ] )
Run Code Online (Sandbox Code Playgroud)

如果您需要选择具有特定条件的随机文档,则可以将其与$matchopperator 一起使用

db.collection.aggregate([ 
    { $sample: {size: 20} }, 
    { $match:{"yourField": value} } 
  ])
Run Code Online (Sandbox Code Playgroud)

小心订单!如果我在我的小数据库中搜索大约100k文档,上面的命令需要15ms,而当你切换顺序时,它是1750ms(慢了100多倍).原因很明显.此外,通过此订单,您可以获得随机20个文档的子集...