簡體   English   中英

Mongoose - RangeError:超過最大調用堆棧大小

[英]Mongoose - RangeError: Maximum Call Stack Size Exceeded

我正在嘗試將文檔批量插入 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]
}); 

因此,答案是響應中的子文檔。 雖然不知道如何解決它....

我遇到了同樣的問題,我開始研究貓鼬源代碼(版本 3.8.14)。 最終它把我帶到了這條線

  • mongoose/node_modules/mongodb/lib/mongodb/collection/core.js ->插入(...) -> 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。 我無法深入挖掘導致它的原因,但認為它可能與 Schema 的 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) {});

確認,但不是錯誤。 Model.collection.insert()繞過 Mongoose,因此您告訴節點驅動程序插入一個包含 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()回數據庫,你真的會好得多。

伙計們! 我今天遇到了那個奇怪的錯誤。 發生這種情況是因為我有一個帶有ref屬性的 Schema,並試圖傳入create / update整個相關文檔。 我已將參數更改為僅_id並且成功了。 奇跡般有效。 我在這里找到了答案(向下滾動到February 21, 2013, 8:05 pm gustavohenke評論)。

我遇到過類似的問題。

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

但這導致了錯誤[RangeError: Maximum call stack size exceeded] 所以我從manyvalues創建了新模型並如下使用它並且它有效。

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

如果在內部更改了manyvalues ,則可能會導致該問題。

如果_id值重復,也會發生這種情況。 大多數情況是您可以從現有記錄創建新記錄。

刪除_id並插入記錄並讓 Mongoose/MongoDb 負責創建 id。

我遇到過同樣的問題。 貓鼬版本是5.13.14 我的堆棧跟蹤是:

RangeError: Maximum call stack size exceeded
    at minimize (...\node_modules\mongoose\lib\document.js:3564:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)
    at minimize (...\node_modules\mongoose\lib\document.js:3576:18)

我找到了兩種解決問題的方法:

  1. 使用toObject()方法:
const model = await MyModel.findOne(conditions);
return model?.toObject();
  1. 在模式的toJSON選項中使用minimize: false
export const MySchema = new Schema({
    ...
}, {
    ...
    toJSON: {
        getters: true,
        // !!! HERE !!!
        minimize: false,
    },
    ...
});

檢查響應對象中的循環引用。 由於循環引用,我遇到了類似的問題。

我有一個類似的問題,我正在使用 $ne 查詢架構中不存在的字段(其他查詢運算符可能有類似的問題)

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

在上面的示例中,我正在測試 test2 而不是 test

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM