Mongoose - RangeError:超出最大调用堆栈大小

时间:2014-06-28 11:32:23

标签: javascript node.js mongodb mongoose

我正在尝试将文档批量插入MongoDB(因此绕过Mongoose并使用本机驱动程序,因为Mongoose不支持批量插入文档数组)。我这样做的原因是为了提高写作速度。

我在下面的代码中收到console.log(err)错误“RangeError:Maximum Call Stack Size Exceeded”:

function _fillResponses(globalSurvey, optionsToSelectRegular, optionsToSelectPiped, responseIds, callback) {
  Response.find({'_id': {$in: responseIds}}).exec(function(err, responses) {
    if (err) { return callback(err); }

    if (globalSurvey.questions.length) {
      responses.forEach(function(response) {
        console.log("Filling response: " + response._id);
        response.answers = [];
        globalAnswers = {};
        globalSurvey.questions.forEach(function(question) {
          ans = _getAnswer(question, optionsToSelectRegular, optionsToSelectPiped, response);
          globalAnswers[question._id] = ans;
          response.answers.push(ans);
        });
      });
      Response.collection.insert(responses, function(err, responsesResult) {
        console.log(err);
        callback()
      });
    } else {
        callback();
      }
  });
} 

类似于:https://stackoverflow.com/questions/24356859/mongoose-maximum-call-stack-size-exceeded

也许是关于Mongoose返回的响应数组的格式,这意味着我不能直接使用MongoDB插入?我在每次回复时都尝试过.toJSON(),但没有运气。

即使只有非常少量的数据,我仍然会收到错误,但是循环并且单独调用每个文档上的Mongoose保存工作正常。

编辑:我认为这与此问题有关:http://howtosjava.blogspot.com.au/2012/05/nodejs-mongoose-rangeerror-maximum-call.html

我的回复架构是:

var ResponseSchema = new Schema({
  user: {
    type: Schema.ObjectId,
    ref: 'User'
  },
  randomUUID: String,
  status: String,
  submitted: Date,
  initialEmailId: String,
  survey: String,
  answers: [AnswerSchema]
}); 

因此,答案是答复中的子文件。不知道如何修复它......

7 个答案:

答案 0 :(得分:30)

我遇到了同样的问题,我开始挖掘猫鼬源代码(版本3.8.14)。最终它引导我进入

这一行
  • mongoose / node_modules / mongodb / lib / mongodb / collection / core.js - > insert (...) - > insertWithWriteCommands (...) - >
  • mongoose / node_modules / mongodb / lib / mongodb / collection / batch / ordered.js - > bulk.insert(docs [i]) - > addToOperationsList(...) - > bson.calculateObjectSize(document,false);

    var bsonSize = bson.calculateObjectSize(document,false);

显然,这会调用BSON.calculateObjectSize,它调用calculateObjectSize然后无限地递归。我无法深入了解导致它的原因,但认为它可能与模仿的mongoose包装器绑定功能有关。由于我将原始数据插入到mongoDB中,一旦我决定将mongoose中的批量插入更改为标准javascript对象,问题就消失了,批量插入正确发生。你也许可以做类似的事情。

基本上,我的代码来自

//EDIT: mongoose.model needs lowercase 'm' for getter method

var myModel = mongoose.model('MyCollection');
var toInsert = myModel();
var array = [toInsert];
myModel.collection.insert(array, {}, function(err, docs) {});

//EDIT: mongoose.model needs lowercase 'm' for getter method

var myModel = mongoose.model('MyCollection');
var toInsert = { //stuff in here 
   name: 'john',
   date: new Date()
};
var array = [toInsert];
myModel.collection.insert(array, {}, function(err, docs) {});

答案 1 :(得分:17)

确认,但不是错误。 Model.collection.insert()绕过Mongoose,所以你告诉节点驱动程序插入一个包含猫鼬内部的对象,如$__等。堆栈溢出可能是因为bson试图计算一个间接引用自己的对象。

长话短说,使用Document.toObject(),它的用途是什么:http://mongoosejs.com/docs/api.html#document_Document-toObject

Response.find({}).exec(function(err, responses) {
  if (err) { 
    return callback(err); 
  }

  if (true) {
    var toInsert = [];
    responses.forEach(function(response) {
      console.log("Filling response: " + response._id);
      response.answers = [];
      [{ name: 'test' }].forEach(function(ans) {
        response.answers.push(ans);
      });
      toInsert.push(response.toObject());
    });
    Response.collection.insert(toInsert, function(err, responsesResult) {
      console.log(err);
    });
  } else {
      callback();
    }
});

此外,即使您修复了堆栈溢出,您指定的代码也不会起作用。由于您正在尝试已经在数据库中的insert()个文档,因为_id冲突,所有插入都将失败。仅使用stream()一次读取一个结果,然后save()将它们返回到db中,你真的会好得多。

答案 2 :(得分:2)

我遇到过类似的问题。

_sharedService.missionConfirmed$.subscribe(
        hero => {
            console.log('confirmed');
            alert('App2Component received hero click: ' + hero);
        });

但这导致错误 [RangeError:超出最大调用堆栈大小] 。 所以我从 manyvalues 创建了新模型,并在下面使用它并且它有效。

//manyvalues is array of objects
schema.methods.somemethod = function(manyvalues,callback) {
    this.model(collection).collection.insertMany(manyvalues,callback);
}

如果在内部更改 manyvalues ,可能会导致此问题。

答案 3 :(得分:1)

家伙!我今天遇到了这个奇怪的错误。之所以发生这种情况,是因为我有一个包含ref属性的架构,并尝试传入create / update整个相关文档。我已经改变了_id的论点,这就是诀窍。奇迹般有效。我找到了答案here(向下滚动到February 21, 2013, 8:05 pm gustavohenke评论)。

答案 4 :(得分:1)

如果_id值重复,也会发生这种情况。大多数情况是您可以从现有记录创建新记录。

删除_id并插入记录并让Mongoose / MongoDb负责创建id。

答案 5 :(得分:0)

检查响应对象中的循环引用。由于循环引用,我遇到了类似的问题。

答案 6 :(得分:-1)

我遇到了类似的问题,就是我在使用$ ne查询模式中不存在的字段(其他查询运算符可能有类似的问题)

var TestSchema = new Schema({
  test:[]
});
...
models.Test.findOne({"test2": {$ne: "t"} })...

在上面的例子中,我正在测试test2而不是test