我在使用mongoose和Nodejs时收到超出最大调用堆栈大小的错误。这是错误
RangeError: Maximum call stack size exceeded
at model.Document.$toObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2045:24)
at model.Document.toJSON (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2362:15)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:252:18)
at cloneArray (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:362:14)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:247:12)
at cloneObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:343:13)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:260:16)
at model.Document.$toObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2092:13)
我相信这意味着我在某处造成无限循环,但我不确定导致错误的原因。路线工作正常,然后我将mongoose-autopopulate插件添加到应用程序。使用令牌正确发送POST到我的驱动器路径后,我收到此错误。没有记录任何内容,服务器停止。
以下是我在drive.js
中的路线示例 router.post('/', function(req, res, next){
var decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, function(err, user){
if (err) {
return res.status(500).json({
title: 'There was a server error',
error: err
});
}
var drive = new Drive({
startAddress: req.body.startAddress,
endAddress: req.body.endAddress,
tripDate: req.body.tripDate,
tripHour: req.body.tripHour,
price: req.body.price,
numberOfPassengers: req.body.numberOfPassengers,
user: user
});
drive.save(function (err, result) {
if(err) {
return res.status(500).json({
title: 'There was an error saving the drive collection',
error: err
});
}
user.drives.push(result);
user.save();
res.status(201).json({
message: 'Drive saved',
obj: result
});
});
});
});
这是相关模型
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.model');
var Trip = require('./trip.model');
var autoPopulate = require('mongoose-autopopulate');
var driveSchema = new Schema({
startAddress: {type: String, required: true, lowercase: true},
endAddress: {type: String, required: true, lowercase: true},
tripDate: {type: Date, required: true},
tripHour: {type: String, required: true},
price: {type: Number, required: true},
numberOfPassengers: {type: Number, required: true},
trip: {type: Schema.Types.ObjectId, ref: 'Trip', autopopulate: true},
user: {type: Schema.Types.ObjectId, ref: 'User', autopopulate: true}
});
driveSchema.post('remove', function(drive) {
User.findById(drive.user, function(err, user) {
user.drives.pull(drive);
user.save();
});
});
driveSchema.plugin(autoPopulate);
module.exports = mongoose.model('Drive', driveSchema);
我的所有模型都遵循相同的方法和查询。有什么具体的我做错了吗?我查了一下,似乎我可以调用一个实例而不是JSON来破坏代码,但我没有经验足以识别该实例的位置,或者是什么导致重新调用的调用为.find()或.where()我正在使用的是打破它。
以下是我的其他型号
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var autopopulate = require('mongoose-autopopulate');
var tripSchema = new Schema({
tripActivated: {type: Boolean},
tripCompleted: {type: Boolean},
driver: {type: Schema.Types.ObjectId, ref: 'Drive', autopopulate: true},
riders: [{type: Schema.Types.ObjectId, ref: 'Ride', autopopulate: true}],
comments: [{type: Schema.Types.ObjectId, ref: 'Comment', autopopulate: true}]
});
tripSchema.post('remove', function(trip) {
User.findById(trip.driver.user, function(err, user) {
user.trips.pull(trip);
user.save();
});
});
// tripSchema.post('remove', function(trip) {
// User.findById(trip.riders.user, function(err, user) {
// user.trips.pull(trip);
// user.save();
// });
// });
tripSchema.plugin(autopopulate);
module.exports = mongoose.model('Trip', tripSchema);
//// NEW MODEL
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.model');
var Trip = require('./trip.model');
var autoPopulate = require('mongoose-autopopulate');
var rideSchema = new Schema({
startAddress: {type: String, required: true, lowercase: true},
endAddress: {type: String, required: true, lowercase: true},
tripDate: {type: Date, required: true},
tripHour: {type: String, required: true},
numberOfPassengers: {type: Number, required: true},
trip: {type: Schema.Types.ObjectId, ref: 'Trip', autopopulate: true},
user: {type: Schema.Types.ObjectId, ref: 'User', autopopulate: true}
});
rideSchema.post('remove', function(ride) {
User.findById(ride.user, function(err, user) {
user.rides.pull(ride);
user.save();
});
});
rideSchema.plugin(autoPopulate);
module.exports = mongoose.model('Ride', rideSchema);
////// NEW MODEL
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var User = require('./user.model');
var autoPopulate = require('mongoose-autopopulate');
var requestSchema = new Schema({
typeOfRequest: {type: String, required: true},
driver: {type: Schema.Types.ObjectId, ref: 'Drive', autopopulate: true},
rider: {type: Schema.Types.ObjectId, ref: 'Ride', autopopulate: true}
});
requestSchema.post('remove', function(request) {
User.findById(request.user, function(err, user) {
user.requests.pull(request);
user.save();
});
});
requestSchema.plugin(autoPopulate);
module.exports = mongoose.model('Request', requestSchema);
////新模型
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var autoPopulate = require('mongoose-autopopulate');
var User = require('./user.model');
var messageSchema = new Schema ({
content: {type: String, required: true},
receiver: {type: Schema.Types.ObjectId, ref: 'User', autopopulate: true },
user: {type: Schema.Types.ObjectId, ref: 'User', autopopulate: true}
});
messageSchema.post('remove', function(message) {
User.findById(message.user, function(err, user) {
user.messages.pull(message);
user.save();
});
});
messageSchema.plugin(autoPopulate);
module.exports = mongoose.model('Message', messageSchema);
深入探讨后,我的错误似乎源于此节点,该代码在node_modules中的mongoose源代码中加注
Document.prototype.$toObject = function(options, json) {
***var defaultOptions = {
transform: true,
json: json,
retainKeyOrder: this.schema.options.retainKeyOrder,
flattenDecimals: true
};***
// _isNested will only be true if this is not the top level document, we
// should never depopulate
if (options && options.depopulate && options._isNested && this.$__.wasPopulated) {
// populated paths that we set to a document
return clone(this._id, options);
}
// When internally saving this document we always pass options,
// bypassing the custom schema options.
if (!(options && utils.getFunctionName(options.constructor) === 'Object') ||
(options && options._useSchemaOptions)) {
if (json) {
options = this.schema.options.toJSON ?
clone(this.schema.options.toJSON) :
{};
options.json = true;
options._useSchemaOptions = true;
} else {
options = this.schema.options.toObject ?
clone(this.schema.options.toObject) :
{};
options.json = false;
options._useSchemaOptions = true;
}
}
for (var key in defaultOptions) {
if (options[key] === undefined) {
options[key] = defaultOptions[key];
}
}
('minimize' in options) || (options.minimize = this.schema.options.minimize);
// remember the root transform function
// to save it from being overwritten by sub-transform functions
var originalTransform = options.transform;
options._isNested = true;
var ret = clone(this._doc, options) || {};
if (options.getters) {
applyGetters(this, ret, 'paths', options);
// applyGetters for paths will add nested empty objects;
// if minimize is set, we need to remove them.
if (options.minimize) {
ret = minimize(ret) || {};
}
}
if (options.virtuals || options.getters && options.virtuals !== false) {
applyGetters(this, ret, 'virtuals', options);
}
if (options.versionKey === false && this.schema.options.versionKey) {
delete ret[this.schema.options.versionKey];
}
var transform = options.transform;
// In the case where a subdocument has its own transform function, we need to
// check and see if the parent has a transform (options.transform) and if the
// child schema has a transform (this.schema.options.toObject) In this case,
// we need to adjust options.transform to be the child schema's transform and
// not the parent schema's
if (transform === true ||
(this.schema.options.toObject && transform)) {
var opts = options.json ? this.schema.options.toJSON : this.schema.options.toObject;
if (opts) {
transform = (typeof options.transform === 'function' ? options.transform : opts.transform);
}
} else {
options.transform = originalTransform;
}
if (typeof transform === 'function') {
var xformed = transform(this, ret, options);
if (typeof xformed !== 'undefined') {
ret = xformed;
}
}
return ret;
};
我设置了mongoose.set('debugger',true);以获得更好的错误。当试图发布ride.js时,应用程序注册POST请求,找到userID,处理新的Ride(基于模型),将骑行插入数据库,然后立即崩溃。
这是mongoose日志的错误
Mongoose: users.ensureIndex({ email: 1 }, { unique: true, background: true })
Successfully connected to localhost:27017/atlas
Mongoose: users.findOne({ _id: ObjectId("59506e1629cdff044664f21c") }, { fields: {} })
(node:1219) DeprecationWarning: Mongoose: mpromise (mongoose's default promise library) is deprecated, plug in your own promise library instead: http://mongoosejs.com/docs/promises.html
Mongoose: rides.insert({ startAddress: 's', endAddress: 's', tripDate: new Date("Fri, 22 Feb 2222 00:00:00 GMT"), tripHour: '8', numberOfPassengers: 2, user: ObjectId("59506e1629cdff044664f21c"), _id: ObjectId("595078cf0b46e704c3091070"), __v: 0 })
events.js:160
throw er; // Unhandled 'error' event
^
RangeError: Maximum call stack size exceeded
at model.Document.$toObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2045:24)
at model.Document.toJSON (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2362:15)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:253:18)
at cloneArray (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:363:14)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:247:12)
at cloneObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:344:13)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:261:16)
at model.Document.$toObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2092:13)
at model.Document.toJSON (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2362:15)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:253:18)
at cloneObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:344:13)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:261:16)
at model.Document.$toObject (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2092:13)
at model.Document.toJSON (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/document.js:2362:15)
at clone (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:253:18)
at cloneArray (/Users/joncorrin/Desktop/workspace/MEAN/atlas-web/node_modules/mongoose/lib/utils.js:363:14)
********** UPDATE
在做了一些挖掘之后,这就是打破应用程序的代码
user.drives.push(result); <----------
user.save();
将数据插入mongodb然后当它试图推送给用户时,它会中断。知道为什么吗?我添加了我的用户模型以供参考。
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var autoPopulate = require('mongoose-autopopulate');
var userSchema = new Schema({
email: {type: String, required: true, unique: true, lowercase:true},
password: {type: String, required: true},
profileImgUrl: {type: String},
fName: {type: String},
lName: {type: String},
yearOfBirth: {type: String},
gender: {type: String},
ratings: [{type: Number}],
comments: [{type: Schema.Types.ObjectId, ref: 'Comment', autopopulate: true}],
messages: [{type: Schema.Types.ObjectId, ref: 'Message', autopopulate: true}],
rides: [{type: Schema.Types.ObjectId, ref: 'Ride', autopopulate: true}],
drives: [{type: Schema.Types.ObjectId, ref: 'Drive', autopopulate: true}],
requests: [{type: Schema.Types.ObjectId, ref: 'Request', autopopulate: true}],
trips: [{type: Schema.Types.ObjectId, ref: 'Trip', autopopulate: true}]
});
userSchema.plugin(mongooseUniqueValidator);
userSchema.plugin(autoPopulate);
module.exports = mongoose.model('User', userSchema);
答案 0 :(得分:0)
问题出在我的用户模型中。我正在使用mongoose-autopopulate插件并将autopopulate设置为其中包含用户实例的真实对象。
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var mongooseUniqueValidator = require('mongoose-unique-validator');
var autoPopulate = require('mongoose-autopopulate');
var userSchema = new Schema({
email: {type: String, required: true, unique: true, lowercase:true},
password: {type: String, required: true},
profileImgUrl: {type: String},
fName: {type: String},
lName: {type: String},
yearOfBirth: {type: String},
gender: {type: String},
ratings: [{type: Number}],
comments: [{type: Schema.Types.ObjectId, ref: 'Comment', autopopulate: true}],
messages: [{type: Schema.Types.ObjectId, ref: 'Message', autopopulate: true}],<---------
rides: [{type: Schema.Types.ObjectId, ref: 'Ride', autopopulate: true}],<---------
drives: [{type: Schema.Types.ObjectId, ref: 'Drive', autopopulate: true}],<-----------
requests: [{type: Schema.Types.ObjectId, ref: 'Request', autopopulate: true}],
trips: [{type: Schema.Types.ObjectId, ref: 'Trip', autopopulate: true}]
});
userSchema.plugin(mongooseUniqueValidator);
userSchema.plugin(autoPopulate);
module.exports = mongoose.model('User', userSchema);
我还在这些模型上将autopopulate设置为true。这在填充给定模型和用户模型之间调用了无限循环。
如果有人遇到此问题。不要像我一样在堆栈溢出上发布一堆代码。弄清楚你打电话回来的电话。就我而言,我在两个可以来回通信的模型上调用autopopulate。