我在不同的计算机上有两个mongo数据库,host1:27017/db1
和host2:27017/db2
在两个数据库上具有相同的集合item
。如何复制所选数据,比如说
db1.item.find({"date": { $gte : "2016-03-15" }})
从db1.item
到db2.item
使用mongo shell。我不想克隆集合(因为它们很大),但只复制选定的数据。
答案 0 :(得分:2)
所以虽然它可能"可能"使用外壳(没有人说它不是)它不是最好的"方式。
" best"方法正在使用mongodump
和mongorestore
。您也不需要"临时转储文件" 。这只是一个问题"管道"从一个输出到另一个:
根据您放置-h
选项的位置实际运行的主机:
mongodump -h host2 -d db2 -c item \
--query '{ "date": { "$gte": "2016-03-15" } }' \
--out - \
| mongorestore -d db1 -c item -
从MongoDB 3.2版本开始,这些命令也可以使用压缩数据。这需要--gzip
和--archive
选项:
mongodump -h host2 -d db2 -c item \
--query '{ "date": { "$gte": "2016-03-15" } }' \
--gzip --archive \
| mongorestore -d db1 -c item --gzip --archive
这总是在数据库之间,特别是在主机之间移动的最快方式。
如果你坚持在shell中写这个,那么你至少应该做对。
当然,你可以使用connect()
或Mongo()
方法来引用远程连接,但这只是故事的一部分,因为一旦连接,你仍然需要有效地处理这个问题。
执行此操作的最佳方法是使用"批量操作",因为这会消除对目标服务器和集合的每个新.insert()
操作的请求和确认的开销。它会减少很多的时间,但仍不如上面使用的实用程序那么高效:
现代MongoDB 3.2有bulkWrite()
:
var db2 = connect('host2/db2');
var operations = [];
db2.item.find({ "date": { "$gte": "2016-03-15" } }).forEach(function(doc) {
operations.push({ "insertOne": { "document": doc } });
// Actually only write every 1000 entries at once
if ( operations.length == 1000 ) {
db.item.bulkWrite(operations,{ "ordered": false })
operations = [];
}
});
// Write any remaining
if ( operations.length > 0 ) {
db.item.bulkWrite(operations,{ "ordered": false });
}
对于MongoDB 2.6版本,还有另一个"bulk"构造函数:
var db2 = connect('host2/db2');
var bulk = db.item.initializeUnorderedBulkOp();
var count = 0;
db2.item.find({ "date": { "$gte": "2016-03-15" } }).forEach(function(doc) {
bulk.insert(doc);
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.item.initializeUnorderedBulkOp();
}
});
if ( count % 1000 != 0 ) {
bulk.execute();
}
当然,较新的方法实际上只是调用相同的基础"较旧的"下面的方法。但主要的一点是其他API的一致性,其中通常的重点是降级"使用服务器版本低于MongoDB 2.6但没有"批量操作"有线协议,然后只为你处理批量中每个操作的循环和提交。
在任何一种情况下,"unordered"方法都是最好的,因为操作实际上是在" parallel"中的服务器上提交的。而不是"连续",这意味着多件事实际上是在同一时间写作。
所以,所有这些都是代码在外部实用程序中的实现方式,实际上是在一个更有条理的,低水平的#34;形成。自然地" shell"不压缩数据"通过电线"通过主机之间的通信,也无法访问“低级别”#34;编写可以使用BSON库和低级代码执行的功能,这两种功能都可以更快地运行。
"转储和恢复"实际上可以直接使用压缩的BSON形式的数据,并以非常有效的方式提交写入。通过这个标记,这是你做这个的最佳选择,而不是自己编写实现。
答案 1 :(得分:0)
我觉得mongodump
& mongorestore
是更普遍的方式。虽然,我能够通过mongo shell(避免任何临时转储文件)找到一种方法来实现这一点。这就是我正在寻找的。 p>
[user@host1 ~]$ mongo
use db1;
var host2db2 = connect("host2:27017/db2")
host2db2.item.find({
"date" : { $gte : "2016-03-15"}
}).forEach(function(doc){
db1.item.insert(doc);
});