这是运行的代码,它返回Range Maximum调用堆栈大小超出错误。 //使用node.js
将10000个值插入mongodb var MongoClient = require('mongodb').MongoClient;
var mongoServer = require('mongodb').Server;
var serverOptions = {
'auto_reconnect': true,
'poolSize': 100
};
var i=0;
var async =require('async');
var mongoClient = new MongoClient(new mongoServer('localhost', 27017, serverOptions));
var db = mongoClient.db('test');
var collection = db.collection('new_file_test');
mongoClient.open(function (err, mongoClient)
{
if(err){console.log(err)};
function start(i,call)
{
if(i<10000) {
call(start);
}
}
function pass(callback)
{
Insert(save);
i++;
callback(i,pass);
}
start(i,pass);
});
function Insert(callback) {
console.log("Inserting" );
var doc={
'trip_paramid':i,
'tripid':'116',
'lattitude':'12.8929183',
'longitude':'77.63627',
'speed':'2',
'heading':'0',
'altitude':'80469',
'address':'qwertyasdfgxcvbn',
'engine_status':'Normal',
'oil_pressure': '83.12',
'water_temp': '28',
'fuel_content':'0',
'brake':'Normal',
'creation_time':'2013-08-31 23:22:17',
'brakelight_status':'Normal',
'battery_status':'12.68',
'event_code':'8',
'dbinsert_time':'2013-08-31 23:24:59',
'gsm_status':'-51',
'cell_id':'45',
'vehicle_id':'123456',
'distance':'0'}
callback(doc);
}
function save(doc)
{
collection.insert(doc, function(err)
{
if (err)
{
console.log('Error occured');
}
else
console.log("Saved");
});
}
如果条件是插入1000行,它可以正常工作,只有在条件超过10000时才会抛出错误。
答案 0 :(得分:1)
循环超过10000次并执行插入是一个坏主意。但您仍然可以使用async library来帮助您解决问题。我之前遇到过这种情况,我使用async.queue来解决这个问题。
<强> Async.js module 即可。
答案 1 :(得分:1)
问题来自你所做的recursive loop:
function start(i, call) {
if (i < 10000) {
call(start);
}
}
function pass(callback) {
Insert(save);
i++;
callback(i, pass);
}
start(i, pass);
您应该将其更改为:
for (var i = 0; i < 10000; i++) {
Insert(save);
}
简化您的代码:
var i = 0;
function pass() {
if (i < 10000) {
Insert(save);
pass(i);
}
i++;
}
pass();
问题来自你以递归方式调用此函数的部分,并且由于javascript没有尾递归消除,callstack不断增长。 V8(nodejs javascript引擎)有它的限制,callstack一旦达到最大定义的大小就会抛出错误。
您还可以查看以下问题以获取更多信息:
这就是修复Maximum call stack size exceeded
错误。但10000看起来像一个巨大的数字。我刚刚运行它,我的机器花了大约3秒钟,用monk
完成循环。使用mongo shell需要大约1秒钟。如果您正在运行服务器,则在循环运行时,您的应用程序无响应。
我建议改为批量插入,并使用node's setImmediate function安排在挂起的I / O事件(如处理新的Web请求)之后运行下一批:
function insert10000(i) {
insert100();
i++;
if (i < 100) {
setImmidiate(insert10000, i);
}
}
function insert100() {
for (var i = 0; i < 100; i++) {
Insert(save);
}
}
由于我们提出了批量插入调用的主题,所以collection.insert方法支持一组文档,而不是只插入一个文档。
所以当我们目前有类似的事情时:
collection.insert(doc1);
collection.insert(doc2);
可以改为:
collection.insert([doc1, doc2]);
实际上这更快。所以您可以将代码更改为:
function insert10000(i) {
insert100(i);
i++;
if (i < 100) {
setImmediate(insert10000, i);
}
}
function insert100(i) {
var docs = [];
for (var l = i + 1000; i < l; i++) {
docs.push({
'trip_paramid':i,
'tripid':'116',
'lattitude':'12.8929183',
'longitude':'77.63627',
'speed':'2',
'heading':'0',
'altitude':'80469',
'address':'qwertyasdfgxcvbn',
'engine_status':'Normal',
'oil_pressure': '83.12',
'water_temp': '28',
'fuel_content':'0',
'brake':'Normal',
'creation_time':'2013-08-31 23:22:17',
'brakelight_status':'Normal',
'battery_status':'12.68',
'event_code':'8',
'dbinsert_time':'2013-08-31 23:24:59',
'gsm_status':'-51',
'cell_id':'45',
'vehicle_id':'123456',
'distance':'0'
});
}
collection.insert(docs, function(err) {
if (err) {
console.log('Error occurred', err);
}
});
}
我测量了它,它比原始情况快两倍。