如何使用 Node.js 驱动程序复制 MongoDB 集合?

5
有没有办法通过Node.js的MongoDB驱动程序复制一个集合?
例如:collection.copyTo("duplicate_collection");
3个回答

3

虽然在服务器端执行 copyTo() 可以实现,但它会阻塞整个 mongod 进程,并且不会在新集合上创建索引。

var copyTo = "function() { db['source'].copyTo('target') };"

db.eval(copyTo, [], function(err, result) {
  console.log(err);
});

同时注意字段类型警告

"使用db.collection.copyTo()时,请检查字段类型,以确保操作在将BSON转换为JSON期间不会从文档中删除类型信息。考虑使用cloneCollection()来保持类型一致性。"


2

如果您经常在生产系统上进行此操作,请尽量避免使用.eval()。它很快,但存在问题。

更好的方法是使用“批量”操作API,并借助“async”库:

db.collection("target",function(err,target) {

    var batch = target.initializeOrderedBulkOp();
    counter = 0;

    var cursor = db.collection("source").find();
    var current = null;       

    async.whilst(
        function() {
            cursor.nextObject(function(err,doc) {
                if (err) throw err;

                // .nextObject() returns null when the cursor is depleted
                if ( doc != null ) {
                    current = doc;
                    return true;
                } else {
                    return false;
                }
            })
        },
        function(callback) {
            batch.insert(current);
            counter++;

            if ( counter % 1000 == 0 ) {
                batch.execute(function(err,result) {    
                    if (err) throw err;
                    var batch = target.initializeOrderedBulkOp();
                    callback();
                });
            }
        },
        function(err) {
            if (err) throw err;
            if ( counter % 1000 != 0 ) 
                batch.execute(function(err,result) {
                    if (err) throw err;

                    // job done
                });
        }
    );    


});

它很快,虽然不如.eval()那么快,但不会阻塞应用程序或服务器。

批量操作通常会执行您提供的所有操作,但使用取模作为限制器可以获得更多控制,并基本上避免一次性加载过多文档到内存中。请记住,无论如何,发送的批量大小不能超过16MB。


我喜欢@Justin的解决方案,因为它可以阻止mongodb进程。不过我应该在问题之前提到这一点。 - Mathew Kurian

0

复制集合的另一种选项是使用聚合方法和 $out 参数。以下是在 async 函数内部的示例:

const client = await MongoClient.connect("mongodb://alt_dev:aaaaa:27018/meteor");
const db = client.db('meteor');
const planPrice = await db.collection('plan_price');
const planPriceCopy = await planPrice.aggregate([{$match: {}}, {$out: planPriceUpdateCollection}]);
await planPriceCopy.toArray();

这将创建原始集合的副本,包括其所有内容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接