3

すべてのアイテムをループせずにすべてのアイテム コレクションを新しいコレクションにコピーする方法はありますか? DBCursor でループする方法を見つけました。

...
DB db = mongoTemplate.getDb();
DBCursor cursor = db.getCollection("xxx").find();

//loop all items in collection
while (cursor.hasNext()) {
   BasicDBObject b = (BasicDBObject) cursor.next();
   // copy to new collection 
   service.createNewCollection(b);
}
...

すべてのアイテムをループせずにJavaでコピーすることを提案できますか?
(Java 実装の mongo シェルではありません) Tnx.

4

5 に答える 5

6

MongoDB 2.6 では、集計の結果をコレクションに書き込む$out 集計演算子が追加されました。これにより、Java ドライバー (私は Java ドライバー バージョン 2.12.0 を使用しました) を使用して、コレクション内のすべての項目を同じデータベース内の別のコレクションにサーバー側でコピーする簡単な方法が提供されます。

// set up pipeline
List<DBObject> ops = new ArrayList<DBObject>();
ops.add(new BasicDBObject("$out", "target")); // writes to collection "target"

// run it
MongoClient client = new MongoClient("host");
DBCollection source = client.getDB("db").getCollection("source")
source.aggregate(ops);

ワンライナーバージョン:

source.aggregate(Arrays.asList((DBObject)new BasicDBObject("$out", "target")));

ドキュメントによると、大規模なデータセット (>100MB) の場合、 allowDiskUse オプション ( Aggregation Memory Restrictions ) を使用することをお勧めしますが、2GB を超えるコレクションで実行したときにその制限に達しなかったため、適用されない場合があります。少なくとも 2.6.0 では、この特定のパイプラインに。

于 2014-05-02T16:24:33.790 に答える
2

オブジェクトの配列を挿入するというアドバイスに従いました。MongoDB コレクションを別のコレクションに移動するより良い方法 これにより、時間が 45 分から 2 分に短縮されました。これがJavaコードです。

        final int OBJECT_BUFFER_SIZE = 2000;
        int rowNumber = 0;
        List<DBObject> objects;
        final int totalRows = cursor.size();
        logger.debug("Mongo query result size: " + totalRows);
            // Loop design based on this:
            // https://stackoverflow.com/questions/18525348/better-way-to-move-mongodb-collection-to-another-collection/20889762#20889762
            // Use multiple threads to improve
            do {
                logger.debug(String.format("Mongo buffer starts row %d - %d copy into %s", rowNumber,
                        (rowNumber + OBJECT_BUFFER_SIZE) - 1, dB2.getStringValue()));
                cursor = db.getCollection(collectionName.getStringValue()).find(qo)
                        .sort(new BasicDBObject("$natural", 1)).skip(rowNumber).limit(OBJECT_BUFFER_SIZE);
                objects = cursor.toArray();
                try {
                    if (objects.size() > 0) {
                        db2.getCollection(collectionName.getStringValue()).insert(objects);
                    }
                } catch (final BSONException e) {
                    logger.warn(String.format(
                            "Mongodb copy %s %s: mongodb error. A row between %d - %d will be skipped.",
                            dB1.getStringValue(), collectionName.getStringValue(), rowNumber, rowNumber
                                    + OBJECT_BUFFER_SIZE));
                    logger.error(e);
                }
                rowNumber = rowNumber + objects.size();
            } while (rowNumber < totalRows);

バッファサイズは重要なようです。10,000 のサイズで問題なく動作しました。ただし、他のさまざまな理由で、小さいサイズを選択しました。

于 2014-04-05T01:41:37.470 に答える
0

これを行うには、google guava を使用できます。イテレータから Set を取得するには、 Sets#NewHashSet(Iterator)を使用できます。

于 2013-04-23T09:10:12.627 に答える