如何使用PyMongo获取MongoDB集合中20%的数据?
大型MongoDB集合抽取20%数据的可行方案
一、按固定间隔抽取(每第5条,最优方案)
这种方式能稳定获取精确的20%数据,适合需要固定子集的场景,实现方式分两种情况:
1. 集合已有有序自增字段(如seq)
如果集合中存在连续整数类型的有序字段(比如自增序列seq),直接用$mod取模过滤:
db.yourCollection.aggregate([ { $match: { $expr: { $eq: [ { $mod: [ "$seq", 5 ] }, 0 ] } } } ])
该方案性能最优,可利用seq字段的索引快速完成过滤。
2. 无有序自增字段(MongoDB 5.0+)
使用$setWindowFields给每个文档添加行号,再按行号取模筛选:
db.yourCollection.aggregate([ { $setWindowFields: { sortBy: { _id: 1 }, // 依赖_id的默认索引保证排序效率 output: { rowNum: { $rowNumber: {} } } } }, { $match: { $expr: { $eq: [ { $mod: [ "$rowNum", 5 ] }, 0 ] } } }, { $project: { rowNum: 0 } }, // 移除临时行号字段 ], { allowDiskUse: true }) // 大数据集需开启磁盘排序支持
注意:需确保MongoDB版本≥5.0,开启allowDiskUse避免内存不足问题。
二、无重复的随机抽取20%数据
如果接受随机子集但不想用$sample,可选择以下两种方案:
1. 固定随机子集(重复执行结果一致)
基于文档唯一标识(如_id)生成哈希值,通过取模筛选固定比例的文档:
db.yourCollection.aggregate([ { $addFields: { hash: { $hashCode: "$_id" } } }, { $addFields: { normalizedHash: { $mod: [ { $abs: "$hash" }, 100 ] } } }, { $match: { normalizedHash: { $lte: 19 } } }, // 筛选0-19区间,对应20%比例 { $project: { hash: 0, normalizedHash: 0 } } ])
该方案利用_id的唯一性保证无重复,且每次执行结果一致,无需额外索引。
2. 实时随机子集(每次执行结果不同)
给每个文档生成0-1的随机数,筛选随机数≤0.2的文档:
db.yourCollection.aggregate([ { $addFields: { randomVal: { $rand: {} } } }, { $match: { randomVal: { $lte: 0.2 } } }, { $project: { randomVal: 0 } } ])
该方案完全随机,无重复文档,但每次执行结果不同,适合不需要固定子集的场景。
方案选型建议
- 优先选择固定间隔抽取,性能稳定且结果可控;
- 若需要随机子集且要求结果可重复,选哈希取模方案;
- 若仅需单次随机抽样,选实时随机方案。
内容的提问来源于stack exchange,提问作者AlonBA
相关产品推荐
相关产品推荐

