有没有办法通过Node.js的MongoDB驱动程序复制一个集合?
例如:
例如:
collection.copyTo("duplicate_collection");
collection.copyTo("duplicate_collection");
虽然在服务器端执行 copyTo()
可以实现,但它会阻塞整个 mongod 进程,并且不会在新集合上创建索引。
var copyTo = "function() { db['source'].copyTo('target') };"
db.eval(copyTo, [], function(err, result) {
console.log(err);
});
同时注意字段类型警告。
"使用db.collection.copyTo()时,请检查字段类型,以确保操作在将BSON转换为JSON期间不会从文档中删除类型信息。考虑使用cloneCollection()来保持类型一致性。"
如果您经常在生产系统上进行此操作,请尽量避免使用.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。
复制集合的另一种选项是使用聚合方法和 $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();
这将创建原始集合的副本,包括其所有内容。