1

以下に、コレクションからすべてのレコード/ドキュメントを取得するためのJavaコードを少し示します。

    DBCollection collection = database.getCollection("collection");

    BasicDBObject select = new BasicDBObject();
    select.put("title", 1);
    select.put("name", 1);

    String random = JSON.serialize(collection.find(select));

ここで、コレクションからランダムに10個のドキュメントを取得したいと思います。

どうすればいいですか?これは可能ですか?

私は他の人の多くの質問を見つけましたが、実際の解決策ではありません。コレクションには約1500のドキュメントがあります。速度はそれほど重要ではありません。

助けてくれてありがとう!

4

2 に答える 2

1

ヒントは次のとおりです。各ドキュメントに乱数(0..1 間隔など) を埋め込み、範囲クエリを使用してランダムなドキュメントを抽出します

たとえば、 collection があるとしtestます。

シェルでは、このコレクションの各ドキュメントをそのような方法で乱数で埋め込むことができます (サーバー側スクリプトを使用):

db.eval(
   function(){
      db.test.find().forEach(
         function(obj){
            obj.rnd = Math.random();
            db.test.save(obj);
         })})

ランダムなドキュメントを抽出します (このクエリは、Java で使用するように簡単に変換できます)。

db.test.findOne({"rnd" : {"$gte" : Math.random()}})

したがって、コードからドキュメントを生成する場合: 永続化する前に、ランダムな値を持つフィールドをドキュメントに追加するだけです。コレクションにしかアクセスできない場合は、サーバー側の js を使用して各ドキュメントにランダム値フィールドを埋め込みます

単純なループを使用すると、必要な数のランダムなドキュメントを抽出できますが、もちろん、同じドキュメントが複数回抽出される場合 (またはクエリに一致するドキュメントがない場合) の状況を処理する必要があります。

于 2012-10-16T13:14:28.257 に答える
0

あなたが達成しようとしているのはSystematic Samplingと呼ばれるものだと思います。

これを実現する方法の 1 つを次に示します。

//...
List<DBObject> result = new ArrayList<DBObject>();
DBCollection collection = database.getCollection("collection");
long count = collection.getCount();
int limit = 10; //or whatever you want

if (count <= limit) {
  DBCursor cursor = collection.find(select);
  while (cursor.hasNext()) {
    result.add(cursor.next());
  }

} else {
  long skip = Math.round((double) count / limit);

  DBCursor cursor = collection.find(select);

  while (result.size() < limit) {
    int offset = (int) ((skip * result.size() + (int) ((Math.random() * skip) % count)) % count);
    System.out.println(offset);
    DBObject next = cursor.skip(offset).next();
    result.add(next);

    cursor = collection.find(select);
  }

}

基本的に、カウントが目的の制限よりも小さい場合、すべてのドキュメントを収集します。そうでない場合は、N (全体のカウント) / n (制限) に等しいスキップを計算します。次に、常に 0 とスキップの間のランダムなオフセットが計算されますが、反復が考慮されます。

例として、100 個のドキュメントがあり、10 個のランダム サンプルが必要な場合、次のバケットごとに 1 つのランダム サンプルを取得します: 1-10、11-20、21-30、31-40、41-50、51-60 、61-70、71-80、81-90、91-100。

于 2012-10-16T13:07:12.707 に答える