2017-10-23 15 views
0

MongoDBには〜600,000件のドキュメントがあります。これらのうち、正確に半分が0に設定されたフィールドを持っていますが、他のフィールドは1に設定されているフィールドは同じです。集計パイプライン(PyMongo経由)でsampleオペレーションを使用してこのコレクションからランダムサンプルを取得しようとすると、 1の値に向かって最初のコレクションが均等に分散されている場合、当該フィールドが1MongoDBの「ランダム」サンプルが大きく歪んだ結果を返す

あるフィールドが0である300〜400を記録し、その後24,000+記録があるかもしれません25,000レコードサンプルで

は、理由がありますこのように大きく異なる分布で結果を返す$sampleを使用すると、コレクションから代表サンプルを取得するにはどうすればよいですか?

ここで私は、クエリのために使用していPyMongoラインです:MongoDBの3.4.9のよう

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

['$ sample'](https://docs.mongodb.com/manual/reference/operator/aggregation/sample/)はサーバー上に実装されているため、言語の実装は効果がありません。 'size'以外の引数オプションはありませんので、非常に「ブラックボックス」であり、実装されているように動作します。特定の値に対して「均等に分散」されることを期待する場合、実際には2つ以上の操作が必要です。均等に分散すると予想される値ごとに1つの操作が必要です。そうでなければ、それは意図したとおりに単に「ランダム」です。 –

答えて

2

、あなたが観察してきたバイアスの理由の一部は$sampleがストレージにほぼ完全に依存しているということですエンジンのランダムカーソル実装(SERVER-19183参照)。これは、コレクションに多くのデータが含まれている場合に、$sampleが実行可能になるように行われます。ただし、ストレージエンジンはBツリー型の実装を使用してソートされた順序でドキュメントを格納するので、本当にランダムな結果を作成することは必ずしも可能ではありません。

$sampleのメカニックにとって、現在のところ2つの機能要求、つまりSERVER-22069SERVER-22068があります。

データの本当に不偏なサンプルが必要な場合は、この時点で自分の$sampleのようなソリューションをローリングするのが最も良い方法でしょう。何かのように:

  1. すべてのコレクションの_idのリストを取得します。
  2. (例えばPythonのrandom.choiceを使用して)このリストのランダムサンプリングを行います。
  3. _idは常にインデックスが作成されているので、あなたがしたいサンプルサイズに応じて合理的にパフォーマンスになり、サンプリング_idを使用して、すべての関連文書を、取得します。
関連する問題