我在不同的机器上有两个 mongo 数据库,host1:27017/db1并且两个数据库上host2:27017/db2都有相同的集合。item例如,如何复制选定的数据
db1.item.find({"date": { $gte : "2016-03-15" }})
Run Code Online (Sandbox Code Playgroud)
从db1.item到db2.item使用 mongo shell。我不想克隆集合(因为它们很大),而是仅复制所选数据。
因此,虽然它“可能”使用 shell(没有人说不是),但这不是“最好”的方式。
“最好”的方法是使用mongodump和mongorestore。您也不需要“临时转储文件”。这只是将输出从一个“管道”传输到另一个的问题:
根据您实际运行该选项的主机来确定您放置该-h选项的位置:
mongodump -h host2 -d db2 -c item \
--query '{ "date": { "$gte": "2016-03-15" } }' \
--out - \
| mongorestore -d db1 -c item -
Run Code Online (Sandbox Code Playgroud)
从 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
Run Code Online (Sandbox Code Playgroud)
这始终是在数据库之间(尤其是主机之间)移动内容的最快方法。
如果你坚持要在 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 });
}
Run Code Online (Sandbox Code Playgroud)
对于 MongoDB 2.6 版本,还有另一个“批量”构造函数:
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();
}
Run Code Online (Sandbox Code Playgroud)
当然,较新的方法实际上只是调用下面相同的底层“旧”方法。但要点是为了与其他 API 保持一致,其中的要点通常是在使用低于 MongoDB 2.6 且没有“批量操作”有线协议的服务器版本时“降级”操作,然后仅处理循环和为您提交批次中的每个操作。
在任何一种情况下, “无序”方法都是最好的,因为操作实际上是在服务器上“并行”而不是“串行”提交的,这意味着多个事物实际上是同时写入的。
所以实际上,所有这些都是代码在外部实用程序中的实现方式,并且实际上以更有组织性和“低级”的形式实现。当然,“shell”不会通过主机之间的通信“通过线路”压缩数据,也无法访问可以使用 BSON 库和低级代码执行的“低级”写入功能,而这两者的工作速度都要快得多。
“转储和恢复”实际上可以直接使用压缩的 BSON 形式的数据,并以非常有效的方式提交写入。从这个意义上讲,这是您执行此操作的最佳选择,而不是自己编写实现代码。