ドキュメントを含むmongoコレクションがあります。すべてのドキュメントには、0 または 1 のフィールドが 1 つあります。データベースから 1000 レコードをランダムにサンプリングし、そのフィールドを持つドキュメントの数を 1 としてカウントする必要があります。このサンプリングを 1000 回行う必要があります。どうすればいいのですか ?
5 に答える
MongoDB 3.0 以前では、SQL 時代の古いトリックを使用しています (ウィキペディアがランダム ページ機能に使用していると思います)。ランダム化する必要があるすべてのオブジェクトに 0 から 1 までの乱数を格納します。そのフィールドを "r" と呼びましょう。次に、「r」にインデックスを追加します。
db.coll.ensureIndex(r: 1);
ランダムな x オブジェクトを取得するには、次を使用します。
var startVal = Math.random();
db.coll.find({r: {$gt: startVal}}).sort({r: 1}).limit(x);
これにより、単一の検索クエリでランダムなオブジェクトが得られます。必要に応じて、これはやり過ぎかもしれませんが、時間の経過とともに多くのサンプリングを行う場合、これはバックエンドに負荷をかけずに非常に効率的な方法です。
mongo
シェルの例を次に示します。 のコレクションcollname
と の対象の値を想定していthefield
ます。
var total = db.collname.count();
var count = 0;
var numSamples = 1000;
for (i = 0; i < numSamples; i++) {
var random = Math.floor(Math.random()*total);
var doc = db.collname.find().skip(random).limit(1).next();
if (doc.thefield) {
count += (doc.thefield == 1);
}
}
これで@Stenniesの回答に対するコメントを編集するつもりでしたが、膨大な量のレコードをスキップする場合は、代わりにここで個別の自動インクリメントIDインデックスを使用することもできます(ここで大きな話をします)。
コレクションのn番目のレコードを見つけようとしていたこの質問によく似た、別の質問に対する別の回答を書きました。
php mongodbはコレクション内のn番目のエントリを見つけます
私の回答の後半では、基本的に、この問題に対処するための 1 つの潜在的な方法について説明しています。もちろん、ランダムな行を取得するには、1000回ループする必要があります。
mongoengine を使用している場合は、SequenceField を使用して増分カウンターを生成できます。
class User(db.DynamicDocument):
counter = db.SequenceField(collection_name="user.counters")
次に、たとえば 100 個のランダムなリストを取得するには、次のようにします。
def get_random_users(number_requested):
users_to_fetch = random.sample(range(1, User.objects.count() + 1), min(number_requested, User.objects.count()))
return User.objects(counter__in=users_to_fetch)
どこに電話するか
get_random_users(100)