我想从MongoDB数据库中检索一组随机文档。到目前为止,经过大量的谷歌搜索,我只看到了一种方法来检索一个随机文档或一组文档从一个随机跳过位置开始,但文档仍然是顺序的。
我尝试过mongoose-simple-random,不幸的是它没有检索到“真正的”随机集。它的作用是跳到随机位置,然后从该位置检索n个文档。
相反,我想使用一个查询(或最少量的查询)来检索像MySQL一样的随机集合,我每次都需要这个列表是随机的。我需要这个效率 - 与MySQL的这种查询相对。我想在MongoDB中重现以下内容:
SELECT * FROM products ORDER BY rand() LIMIT 50;
这可能吗?我正在使用Mongoose,但任何适配器的示例 - 甚至是直接的MongoDB查询 - 都很酷。
我见过一种向每个文档添加字段的方法,为每个字段生成一个随机值,并使用{rand: {$gte:rand()}}
我们想要随机化的每个查询。但是,我担心的是理论上两个查询可以返回相同的集合。
答案 0 :(得分:2)
您可以通过有效的方式执行两项请求:
db.products.find({}, { '_id' : 1 })
。特别重要的是索引完全支持您的第一个查询(因为它是“_id”)。这个索引可能完全在内存中(否则你可能会遇到性能问题)。因此,在运行第一个查询时只读取索引,而且速度非常快。
虽然第二个查询意味着阅读实际文档,但索引会有很多帮助。
如果你可以这样做,你应该尝试。
答案 1 :(得分:0)
我不认为MySQL ORDER BY rand()
特别有效 - 据我所知,它基本上为每一行分配一个随机数,然后对此随机数列上的表进行排序并返回前N个结果
如果您愿意接受对集合插入的一些开销,则可以减少在一个范围内生成N个随机整数的问题。为每个文档添加一个计数器字段:每个文档将按顺序分配一个唯一的正整数。只要分配是唯一的并且数字是连续的,并且您要么不删除文档,要么使计数器文档方案复杂化以处理漏洞,那么哪个文档得到什么数字并不重要。您可以通过两次插入来完成此操作。在单独的counter
集合中,保留包含未用于计数器的第一个数字的文档。发生插入时,首先findAndModify
计数器文档检索下一个计数器值并以原子方式递增计数器值。然后插入带有计数器值的新文档。要查找N个随机值,找到最大计数器值,然后在max计数器定义的范围内生成N个不同的随机数,然后使用$in
检索文档。大多数语言都应该有随机库来处理范围内的N个随机整数。