我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
我想从一个巨大的集合(1亿条记录)中获得一个随机记录。
最快最有效的方法是什么?
数据已经在那里,没有字段可以生成随机数并获得随机行。
当前回答
MongoDB 3.2更新
3.2在聚合管道中引入了$sample。
还有一篇很好的博客文章是关于如何将其付诸实践的。
对于旧版本(以前的答案)
这实际上是一个功能请求:http://jira.mongodb.org/browse/SERVER-533,但它是在“不会修复”下提交的。
烹饪书中有一个非常好的方法,可以从集合中随机选择一个文档:http://cookbook.mongodb.org/patterns/random-attribute/
套用这个方法,你可以给你的文档分配随机数:
db.docs.save( { key : 1, ..., random : Math.random() } )
然后随机选择一个文档:
rand = Math.random()
result = db.docs.findOne( { key : 2, random : { $gte : rand } } )
if ( result == null ) {
result = db.docs.findOne( { key : 2, random : { $lte : rand } } )
}
同时使用$gte和$lte进行查询,以找到与rand最接近的随机数的文档。
当然你要在随机场上建立索引
db.docs.ensureIndex( { key : 1, random :1 } )
如果您已经在查询一个索引,只需删除它,将random: 1附加到它,然后再次添加它。
其他回答
您还可以在执行查询后使用shuffle-array
Var shuffle = require('shuffle-array');
Accounts.find (qry函数(呃,results_array) { newIndexArr = shuffle (results_array);
有效可靠的方法是:
在每个文档中添加一个名为“random”的字段,并为其分配一个随机值,为该随机字段添加一个索引,如下所示:
让我们假设我们有一个名为“links”的网络链接集合,我们想从它中随机链接:
link = db.links.find().sort({random: 1}).limit(1)[0]
为了确保同一个链接不会第二次弹出,用一个新的随机数更新它的随机场:
db.links.update({random: Math.random()}, link)
现在可以使用聚合了。 例子:
db.users.aggregate(
[ { $sample: { size: 3 } } ]
)
去看医生。
MongoDB现在有$rand
要选择n个非重复项,请使用{$addFields: {_f: {$rand:{}}}}进行聚合,然后按_f进行$sort和$limit n。
当我面对类似的解决方案时,我回溯并发现业务请求实际上是为了创建所呈现的库存的某种形式的轮换。在这种情况下,有更好的选择,它们有来自Solr这样的搜索引擎的答案,而不是MongoDB这样的数据存储。
In short, with the requirement to "intelligently rotate" content, what we should do instead of a random number across all of the documents is to include a personal q score modifier. To implement this yourself, assuming a small population of users, you can store a document per user that has the productId, impression count, click-through count, last seen date, and whatever other factors the business finds as being meaningful to compute a q score modifier. When retrieving the set to display, typically you request more documents from the data store than requested by the end user, then apply the q score modifier, take the number of records requested by the end user, then randomize the page of results, a tiny set, so simply sort the documents in the application layer (in memory).
如果用户的范围太大,可以将用户划分为行为组,按行为组而不是按用户进行索引。
如果产品范围足够小,您可以为每个用户创建一个索引。
我发现这种技术效率更高,但更重要的是在创建相关的、有价值的软件解决方案使用体验方面更有效。