定义
$sample从输入文档中随机选择指定数量的文档。
$sample阶段语法:{ $sample: { size: <positive integer N> } } N是随机选择的文档数量。 将N设置为大于或等于1的整数。
行为
伪随机游标行为
如果以下所有条件均为 true,则$sample 将使用伪随机游标选择N 文档:
$sample是管道的第一个阶段。N少于集合中文档总数的 5%。注意
您无法配置
$sample用于确定何时扫描整个集合的阈值。阈值为 5%。如果大小大于集合中文档总数的 5%,则$sample按生成的随机值执行 top-k 排序。如果示例文档大于 100MB,则 top-k 排序可能会溢出到磁盘。该集合包含 100 多个文档。
伪随机游标不能保证均匀的随机示例。它通过随机降序排列集合的内部B-Tree结构来选择文档,因此结果可能会偏向集合的某些部分。在以下情况下更有可能出现偏差:
集合中的文档分布式不均匀,导致树结构不平衡。
该集合有大量已删除的文档。
大量文档对游标的ACID 事务不可见。
如果您的使用案例需要统一示例,请避免使用伪随机游标。为此,请在另一个阶段后运行$sample,或将 N设立为超过集合中文档的 5%。
随机排序行为
如果前面的任何条件为假,则$sample :
读取之前的聚合阶段或集合扫描输出的所有文档。
分片集群
如果在分片集群中使用 $sample,则每个分片都会独立执行采样操作。mongos 对每个分片的采样操作的合并结果进行采样,并返回所请求的文档数。
示例
本部分展示了使用以下 users 集合的聚合管道示例:
db.users.insertMany( [ { _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 } ] )
以下聚合操作从集合中随机选择 3 个文档:
db.users.aggregate( [ { $sample: { size: 3 } } ] )
此操作会返回三个随机文档。
要使用MongoDB Node.js驱动程序将 $sample 阶段添加到聚合管道,请在管道对象中使用 $sample操作符。
以下示例创建了一个管道阶段,该阶段从输入集合中返回五个随机文档。然后,该示例运行聚合管道:
const pipeline = [{ $sample: { size: 5 } }]; const cursor = collection.aggregate(pipeline); return cursor;