You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 09:05:19