Javascript 插入文档循环-范围错误:超过最大调用堆栈大小
我正在用node和mongodb迈出我的第一步,最近我遇到了这个问题 以下是我正在尝试做的,我有一个文件,其中包含我想添加到mongo db的国家列表。这将是我运行应用程序的种子机制的一部分 我加载json,然后遍历对象集合,并将它们逐个添加到“Countries”集合中。 但是,每次运行代码时,我都会遇到一个RangeError:超出了最大调用堆栈大小 我在谷歌上搜索过,但没有一个建议的解决方案适合我。 我猜我的insertCountry函数有问题 无论如何,这是我的代码:Javascript 插入文档循环-范围错误:超过最大调用堆栈大小,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我正在用node和mongodb迈出我的第一步,最近我遇到了这个问题 以下是我正在尝试做的,我有一个文件,其中包含我想添加到mongo db的国家列表。这将是我运行应用程序的种子机制的一部分 我加载json,然后遍历对象集合,并将它们逐个添加到“Countries”集合中。 但是,每次运行代码时,我都会遇到一个RangeError:超出了最大调用堆栈大小 我在谷歌上搜索过,但没有一个建议的解决方案适合我。 我猜我的insertCountry函数有问题 无论如何,这是我的代码: var mongo
var mongoose = require('mongoose');
var countries = require('./seed/countries.json');
// mongodb
var Country = mongoose.Schema({
name: String,
code: String,
extra: [Extra]
});
var Extra = mongoose.Schema({
exampleField: Boolean,
anotherField: Boolean
});
var mCountry = mongoose.model('Countries', Country);
var mExtra = mongoose.model('Extras', Extra);
// do connection
mongoose.connect('...');
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error'));
db.once('open', function callback() {
});
// async function
var insertCountry = function(document, callback) {
db.model('Countries').count({code: document.code}, function (err, count) {
if (count < 1) {
db.collection('Countries').insert(document, function (err, result) {
if (!err) {
console.log('country ' + document.name + ' added');
}
else {
console.log('- [' + document.name + '] ' + err);
}
});
}
callback(null,document);
});
};
// doing countries
var Country = mongoose.model('Countries');
var Extras = mongoose.model('Extras');
for(i = 0; i < countries.length; i++)
{
nCountry = new Country();
nCountry.name = countries[i].name;
nCountry.code = countries[i].code;
nCountry.benefits = new Extras();
nCountry.benefits.exampleField = false;
nCountry.benefits.anotherField = false;
insertCountry(nCountry, function (err, value) {
console.log(value.name + ' added to collection (callback)');
});
}
我一直在使用我发现的一些指南来构建它,所以这可能不是最佳代码。欢迎分享任何最佳实践、标准、指南或教程 您的回拨位置错误。在您从它自己的回调返回之前,它不会等待插入操作完成。更改您的代码:
var insertCountry = function(document, callback) {
db.model('Countries').count({code: document.code}, function (err, count) {
if (count < 1) {
db.collection('Countries').insert(document, function (err, result) {
if (!err) {
console.log('country ' + document.name + ' added');
}
else {
console.log('- [' + document.name + '] ' + err);
}
callback(null,document);
});
}
});
};
数组仍然存在问题,如果超出调用堆栈限制,那么数组必须相当大。您可能应该考虑使用事件流来处理它,而不是将内存中的所有内容加载到阵列中
就个人而言,如果您只是尝试不为字段插入重复项,并且MongoDB 2.6可用,那么我只会在无序操作中使用,并允许在重复项上出现非致命故障。再加上批量操作是成批发送的,而不是一次发送一个,这比检查每个请求是否存在要高效得多:
var Country = mongoose.Schema({
name: String,
code: { type: String, unique: true }, // define a unique index
extra: [Extra]
});
var insertCountries = function(countries,callback) {
var bulk = Country.collection.initializeUnorderedBulkOp();
var counter = 0;
async.eachSeries(
countries,
function(current,callback) {
// same object construction
bulk.insert(nCountry);
counter++;
// only send once every 1000
if ( counter % 1000 == 0 ) {
bulk.execute(function(err,result) {
// err should generally not be set
// but result would contain any duplicate errors
// along with other insert responses
// clear to result and callback
bulk = Country.collection.initializeUnorderedBulkOp();
callback();
});
} else {
callback();
}
},
function(err) {
// send anything still queued
if ( counter % 1000 != 0 )
bulk.execute(function(err,result) {
// same as before but no need to reset
callback(err);
});
}
);
};
mongoose.on("open",function(err,conn) {
insertCountries(countries,function(err) {
console.log("done");
});
});
请记住,与直接在mongoose模型上实现的方法不同,本机驱动程序方法要求在调用它们之前实际建立连接。Mongoose会为您排队,但在其他情况下,您需要确保连接实际已打开。这里使用了open事件的示例
也来看看s。如果您正在构造一个足够大的数组,由于缺少回调执行而导致问题,那么您可能不应该从任何源代码将其全部加载到内存中。源代码与如上所示的方法相结合的流处理应该能够提供高效的加载。我将代码更改为使用异步库,但运气不佳。没有使用批量插入api,因为这要求我直接使用mongo而不是mongoose。我无法克服调用堆栈的问题。因此,解决办法是只调用Country.createcountries,它就像一个符咒。谢谢你的帮助,尼尔!
var Country = mongoose.Schema({
name: String,
code: { type: String, unique: true }, // define a unique index
extra: [Extra]
});
var insertCountries = function(countries,callback) {
var bulk = Country.collection.initializeUnorderedBulkOp();
var counter = 0;
async.eachSeries(
countries,
function(current,callback) {
// same object construction
bulk.insert(nCountry);
counter++;
// only send once every 1000
if ( counter % 1000 == 0 ) {
bulk.execute(function(err,result) {
// err should generally not be set
// but result would contain any duplicate errors
// along with other insert responses
// clear to result and callback
bulk = Country.collection.initializeUnorderedBulkOp();
callback();
});
} else {
callback();
}
},
function(err) {
// send anything still queued
if ( counter % 1000 != 0 )
bulk.execute(function(err,result) {
// same as before but no need to reset
callback(err);
});
}
);
};
mongoose.on("open",function(err,conn) {
insertCountries(countries,function(err) {
console.log("done");
});
});