首页 文章

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

提问于
浏览
26

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

我在下面的代码中收到console.log(错误)中的错误“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]
});

因此,答案是答复中的子文件 . 不知道怎么解决它虽然....

6 回答

  • 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) {});
    
  • 2

    确认,但不是错误 . 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();
        }
    });
    

    此外,您指定的代码赢得了't work even if you fix the stack overflow. Since you'重新尝试已经在数据库中的文档,由于 _id 冲突,所有插入都将失败 . 你最好只使用一个stream()来一次读取一个结果,然后将它们返回到数据库中 .

  • 1

    我遇到过类似的问题 .

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

    但这导致了错误 [RangeError: Maximum call stack size exceeded] . 所以我从很多值创建了新模型,并将其用于下面并且它有效 .

    schema.methods.somemethod = function(manyvalues,callback){
         var list = JSON.parse(JSON.stringify(manyvalues));//created a new object.
         this.model(collection).collection.insertMany(list,callback);
    }
    

    如果在内部更改了许多值,则可能会导致此问题 .

  • 17

    伙计们!我今天遇到了这个奇怪的错误 . 它发生的原因是我有一个带有 ref 属性的Schema并试图传入 create / update 整个相关文档 . 我已经将参数更改为 _id 而且这样做了 . 奇迹般有效 . 我找到了答案here(向下滚动到 February 21, 2013, 8:05 pm gustavohenke 评论) .

  • -1

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

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

  • 1

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

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

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

相关问题