MongoDB:使用mongo shell将选定的数据从一台主机/机器复制到另一台主机/机器

时间:2016-03-25 20:48:58

标签: mongodb

我在不同的计算机上有两个mongo数据库,host1:27017/db1host2:27017/db2在两个数据库上具有相同的集合item。如何复制所选数据,比如说

db1.item.find({"date": { $gte : "2016-03-15" }})

db1.itemdb2.item使用mongo shell。我不想克隆集合(因为它们很大),但只复制选定的数据。

2 个答案:

答案 0 :(得分:2)

所以虽然它可能"可能"使用外壳(没有人说它不是)它不是最好的"方式。

使用查询转储和还原

" best"方法正在使用mongodumpmongorestore。您也不需要"临时转储文件" 。这只是一个问题"管道"从一个输出到另一个:

根据您放置-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

如果你坚持在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(避免任何临时转储文件)找到一种方法来实现这一点。这就是我正在寻找的。

[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);
});

致记:Save Subset of MongoDB Collection to Another Collection