来自MongoDB的“随机”样本返回严重偏差的结果

时间:2017-10-23 00:55:13

标签: mongodb random aggregation-framework pymongo

我在MongoDB中有一个包含约600,000个文档的集合。其中,正好一半的字段设置为0,而其他字段设置为1.当我尝试使用聚合管道中的sample操作从此集合中获取随机样本时(通过PyMongo) ,它严重偏向1值。

在25,000个记录样本中,可能有300-400条记录,其中字段为0,然后是24,000多条记录,其中有关字段为1.

如果初始集合是平均分配的,那么为什么使用$sample返回的结果具有如此大不相同的分布,以及如何从集合中获取代表性样本?

这是我用于查询的PyMongo行:

cursor = foo_database.bar_collection.aggregate( [ { "$sample": { "size": 25000} } ])

1 个答案:

答案 0 :(得分:2)

从MongoDB 3.4.9开始,您观察到偏见的部分原因是$sample几乎完全依赖于存储引擎的随机游标实现(参见SERVER-19183 })。这样做是为了在集合包含大量数据时$sample可以执行。但是,由于存储引擎使用B树类型实现以排序顺序存储文档,因此并不总是能够创建真正随机的结果。

目前有两项针对更好$sample机制的功能请求,即SERVER-22069SERVER-22068

话虽如此,如果您需要真正无偏见的数据样本,那么滚动您自己的$sample类解决方案可能是此时继续进行的最佳方式。类似的东西:

  1. 获取集合中所有_id的列表。
  2. 在此列表中执行随机抽样(例如,使用Python' s random.choice)。
  3. 使用抽样的_id获取所有相关文档,根据您想要的样本大小,这将是合理的,因为_id始终被编入索引。