Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/400.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 插入文档循环-范围错误:超过最大调用堆栈大小_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

Javascript 插入文档循环-范围错误:超过最大调用堆栈大小

Javascript 插入文档循环-范围错误:超过最大调用堆栈大小,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我正在用node和mongodb迈出我的第一步,最近我遇到了这个问题 以下是我正在尝试做的,我有一个文件,其中包含我想添加到mongo db的国家列表。这将是我运行应用程序的种子机制的一部分 我加载json,然后遍历对象集合,并将它们逐个添加到“Countries”集合中。 但是,每次运行代码时,我都会遇到一个RangeError:超出了最大调用堆栈大小 我在谷歌上搜索过,但没有一个建议的解决方案适合我。 我猜我的insertCountry函数有问题 无论如何,这是我的代码: var mongo

我正在用node和mongodb迈出我的第一步,最近我遇到了这个问题

以下是我正在尝试做的,我有一个文件,其中包含我想添加到mongo db的国家列表。这将是我运行应用程序的种子机制的一部分

我加载json,然后遍历对象集合,并将它们逐个添加到“Countries”集合中。 但是,每次运行代码时,我都会遇到一个RangeError:超出了最大调用堆栈大小

我在谷歌上搜索过,但没有一个建议的解决方案适合我。 我猜我的insertCountry函数有问题

无论如何,这是我的代码:

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