2013-07-02 85 views
2

我想从mysql导入一个表到mongodb直接没有任何架构更改。mongodb nodejs多个插入问题

我写了一个小节点脚本,我的问题是我实现它的方式。

也许我在循环中使用mongo db插入限制时遇到了一些限制。 我认为这个问题不会发生,如果它是反向的(可能不是!)

所以这里的东西。 mysql表中的行超过100,000,但是当循环命中超过30000时,插入的项目数量会减少。

所以我们假设在使用下面提到的脚本完成导入后,如果mysql表中有100,000个项目,那么我最多只能得到37000左右。

我强烈的怀疑是在节点脚本/节点mongodb连接器,或者脚本中的一些错误或最后在mongodb并发db插入限制。

我粘贴下面的脚本。 希望我能解决它。

感谢,

var http = require('http'), 
    mysql = require('mysql'), 
    mongo = require('mongodb').MongoClient, 
    format = require('util').format; 
var connection = mysql.createConnection({ 
    user: "xxx", 
    password: "xxx", 
    database: "mydb" 
}); 

connection.connect(); 
var query = "select * from mytable"; 
var mysqlrows = ''; 
connection.query(query, function(err,rows,fields){ 
    if(err) throw err; 

    console.log(rows.length+'rows found.'); 

    mongo.connect('mongodb://root:[email protected]:27017/mydb', function(err, db){ 
    if (err) 
     throw err; 

    var collection = db.collection('mytable'); 
    for(var i=0; i<rows.length;i++) 
    { 
     //console.log(JSON.stringify(rows[i])); 

     (function(i){ 
     collection.insert(rows[i],function(err,docs){}); 
     console.log(i); 
     })(i); 
    } 

    db.close();   
    });  
}); 
connection.end(); 
+0

'insert'可以接受一系列文档;你是否尝试过直接将'rows'传递给'insert'而不是一个一个的? – JohnnyHK

+0

感谢您的提示,我试图删除循环,然后尝试插入整个“行”数组本身。它的确如你所说的那样工作,但在这里又出现了一个问题。如果“rows”数组的计数小于1150,它可以完美地工作,但是如果根据我的测试,行数大于1200左右,它会再次失败。在将大量行同时插入到mongdb的方法中有些问题非常严重。这里我再次怀疑某种mongodb多重插入限制。但是这在mongo db limits文档中没有提及。 [http://docs.mongodb.org/manual/reference/limits/] –

回答

0

要确保你从MySQL获得的所有数据,试图访问的最后一排。如果你能得到它,使用mongodb的标志w和j来确保每个调用在移到下一个之前插入数据。使用w和j标志,您应该考虑使用和array在每个调用中插入多行来插入多个数据。

+0

感谢@innospg,mysql确实返回了所有100,000行,因为它已由此行确认'console.log(rows.length +'rows found。')。 );'在脚本中。你在说什么w&j旗帜?这是关于我正在使用的nodejs驱动程序的具体情况? –

+0

w和j是mongodb上一版本中的写入关注参数。要调试您的代码,请将安全选项设置为true并检查回调函数的参数err。 – innoSPG

+0

谢谢我猜mongodb节点驱动器插入选项'safe:true'与'w:1'相同。同时设置'j:1'选项,即启用日志功能,即使mongod进程失败,写操作也会安全地自动设置'w:1'标志。对于我的情况'j:1'标志不是一个问题,它是一个小的导入脚本,所有项目的计数都记录在脚本本身中。我认为'j:1'选项应该始终适用于生产插入使用。 –

2

问题在于,在通过db.close();调用关闭与MongoDb的连接之前,您并未等待insert操作完成。您需要跟踪未完成的异步请求,然后在全部完成后才调用db.close();

+0

感谢队友,看起来像是这样,刚刚从代码中移除了'db.close()'&'connection.end()'并且它在一回合中都能正常工作。但是我会用最终代码来更新这个线程,它将使用这个概念,但仍然关闭所有的连接,以便解决方案变成最终的。 –

+0

我发现使用['async.series'](https://github.com/caolan/async)在管理数据库更新操作方面很有帮助,特别是在查看了这个[answer](http://stackoverflow.com/a/ 18341176/549155)from [freakish](http://stackoverflow.com/users/645551/freakish) – mjmoody383