熟悉 MySQL 的同学应该都知道可以通过类似如下语句简单的获取一张表里随机的 N 条记录:
SELECT * FROM table ORDER BY RAND() LIMIT N;
在 MongoDB 里应该如何操作呢?官方在 3.2 版本带来了直接的解决方案:
$sample (aggregation)
具体应该如何操作,官方也给出了一个示例,假设 Collection users 有如下记录:
{ "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }
{ "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false }
{ "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true }
{ "_id" : 4, "name" : "li", "q1" : true, "q2" : false }
{ "_id" : 5, "name" : "annT", "q1" : false, "q2" : true }
{ "_id" : 6, "name" : "li", "q1" : true, "q2" : true }
{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true }
那么可以通过命令 db.users.aggregate( [ { $sample: { size: N } } ] )
获取随机的 N 条记录,如:
mongos> db.users.aggregate( [ { $sample: { size: 3 } } ] )
{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true }
{ "_id" : 4, "name" : "li", "q1" : true, "q2" : false }
{ "_id" : 1, "name" : "dave123", "q1" : true, "q2" : true }
mongos> db.users.aggregate( [ { $sample: { size: 3 } } ] )
{ "_id" : 7, "name" : "ty", "q1" : false, "q2" : true }
{ "_id" : 3, "name" : "ahn", "q1" : true, "q2" : true }
{ "_id" : 2, "name" : "dave2", "q1" : false, "q2" : false }
mongos>
$sample 会使用如下两种方式来获取随机的 N 条记录,具体使用哪种方式取决于如下条件:
- $sample 处于聚合管道的第一阶段;
- N 小于总文档数量的 5% ;
- 集合(Collection)中的文档数量大于 100;
当以上 3 个条件都满足时,$sample 将通过伪随机的游标来获取记录。当任一条件不满足时,$sample 将进行集合扫描,并通过随机排序来选择相应的 N 条记录。
需要注意的是:
- 当使用随机排序来获取记录时,排序操作会有 100 MB 的内存限制,具体可以参考 $sort and Memory Restrictions;
- $sample 有可能多次返回同一条记录(document);
- 尝试在一张十亿级的 Collection 上获取 1W 条随机记录,耗时约 2.5 秒,供参考;
参考文档:
- https://docs.mongodb.com/manual/reference/operator/aggregation/sample/
- https://jira.mongodb.org/browse/SERVER-533
您可能还喜欢以下文章
- 可能是全网最全的 ulimit 配置说明了
- WireGuard 浅显体验
- 网易游戏 MySQL-MongoDB 运维及 DBA 招聘
- 美区 Apple ID 充值攻略
- MongoDB 4.2 流控 FlowControl 机制走读
相关评论
comments powered by Disqus