angular-fullstack 服务器重启后 Mongoose populate() 为空
Mongoose populate() is null after server restart in angular-fullstack
我有 "Video" 猫鼬模式,它引用了 "owner",这是对 "User" 模式的引用。我正在使用 Angular-Fullstack Yeoman 生成器
video.model.js:
'use strict';
// load the things we need
var mongoose = require('mongoose'), Schema = mongoose.Schema;
var videoSchema = mongoose.Schema({
type : { type: String, enum: ['youtube', 'vimeo', 'local'], required: true },
owner : { type: String, ref: 'User', required : true },
date : { type: Date, default: Date.now },
name : { type: String, required: true },
sourcemedia : { type: String, required: true, unique: true}
});
// keep our virtual properties when objects are queried
videoSchema.set('toJSON', { virtuals: true });
videoSchema.set('toObject', { virtuals: true });
用户模式(样板 Yeoman angular-fullstack 代码):
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var crypto = require('crypto');
var authTypes = ['github', 'twitter', 'facebook', 'google'];
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
role: {
type: String,
default: 'user'
},
hashedPassword: String,
provider: String,
salt: String,
facebook: {},
google: {},
github: {}
});
/**
* Virtuals
*/
UserSchema
.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashedPassword = this.encryptPassword(password);
})
.get(function() {
return this._password;
});
// Public profile information
UserSchema
.virtual('profile')
.get(function() {
return {
'name': this.name,
'role': this.role
};
});
// Non-sensitive info we'll be putting in the token
UserSchema
.virtual('token')
.get(function() {
return {
'_id': this._id,
'role': this.role
};
});
/**
* Validations
*/
// Validate empty email
UserSchema
.path('email')
.validate(function(email) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return email.length;
}, 'Email cannot be blank');
// Validate empty password
UserSchema
.path('hashedPassword')
.validate(function(hashedPassword) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return hashedPassword.length;
}, 'Password cannot be blank');
// Validate email is not taken
UserSchema
.path('email')
.validate(function(value, respond) {
var self = this;
this.constructor.findOne({email: value}, function(err, user) {
if(err) throw err;
if(user) {
if(self.id === user.id) return respond(true);
return respond(false);
}
respond(true);
});
}, 'The specified email address is already in use.');
var validatePresenceOf = function(value) {
return value && value.length;
};
/**
* Pre-save hook
*/
UserSchema
.pre('save', function(next) {
if (!this.isNew) return next();
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1)
next(new Error('Invalid password'));
else
next();
});
/**
* Methods
*/
UserSchema.methods = {
/**
* Authenticate - check if the passwords are the same
*
* @param {String} plainText
* @return {Boolean}
* @api public
*/
authenticate: function(plainText) {
return this.encryptPassword(plainText) === this.hashedPassword;
},
/**
* Make salt
*
* @return {String}
* @api public
*/
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
},
/**
* Encrypt password
*
* @param {String} password
* @return {String}
* @api public
*/
encryptPassword: function(password) {
if (!password || !this.salt) return '';
var salt = new Buffer(this.salt, 'base64');
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
}
};
module.exports = mongoose.model('User', UserSchema);
我有一个控制器,它具有获取一个视频的功能 (exports.show) 和一个获取多个视频的功能 (exports.index),video.controller.js:
'use strict';
var _ = require('lodash');
var Video = require('./video.model');
// Get list of videos
exports.index = function(req, res) {
Video.find()
.populate('owner')
.exec(function (err, videos) {
console.log("Pulled videos:", videos);
if(err) { return handleError(res, err); }
return res.json(200, videos);
});
};
// Get a single video
exports.show = function(req, res) {
Video.findById(req.params.id)
.populate('owner')
.exec(function (err, video) {
if(err) { return handleError(res, err); }
if(!video) { return res.send(404); }
return res.json(video);
});
};
如果将视频添加到数据库并在重新启动服务器之前对其进行查询,则一切都会按预期运行。 populate 函数有效,每个视频都会填充一个 "owner"。一旦服务器重新启动,任何查询的所有所有者都是 null
,我不知道为什么。如果我查看 Mongo CLI 中的文档,视频有 "owner" 这是用户的字符串“_id”(这是预期的)。
> mongo
MongoDB shell version: 2.4.12
> db.videos.find()
{ "owner" : "550a11cb5b3bf655884fad40", "type" : "youtube", "name" : "test", "sourcemedia" : "xxxxxxx", "_id" : ObjectId("550a11d45b3bf655884fad41"), "date" : ISODate("2015-03-18T04:00:00Z"), "__v" : 0 }
我尝试使用 Schema.Type.ObjectId
作为视频 "owner" 的类型,但我得到了相同的结果:
owner : { type: Schema.Types.ObjectId, ref: 'User', required : true },
为什么我的视频的 "owner" 属性返回 null?
Mongo版本:2.4.12
Mongoose 版本:3.8.24
呸!使用 angular-fullstack 生成器,用户的 table 会在您每次重新启动服务器时自动重新播种。我的填充没有工作,因为每次重新启动时唯一用户 _id 都被擦除。
在 server/config/seed.js
中找到了这条评论,它告诉了我解决方案...
/**
* Populate DB with sample data on server start
* to disable, edit config/environment/index.js, and set `seedDB: false`
*/
为了解决我改变了server/config/environment/development.js
对象(对我来说在第8行)
seedDB: true
到
seedDB: false
我有 "Video" 猫鼬模式,它引用了 "owner",这是对 "User" 模式的引用。我正在使用 Angular-Fullstack Yeoman 生成器
video.model.js:
'use strict';
// load the things we need
var mongoose = require('mongoose'), Schema = mongoose.Schema;
var videoSchema = mongoose.Schema({
type : { type: String, enum: ['youtube', 'vimeo', 'local'], required: true },
owner : { type: String, ref: 'User', required : true },
date : { type: Date, default: Date.now },
name : { type: String, required: true },
sourcemedia : { type: String, required: true, unique: true}
});
// keep our virtual properties when objects are queried
videoSchema.set('toJSON', { virtuals: true });
videoSchema.set('toObject', { virtuals: true });
用户模式(样板 Yeoman angular-fullstack 代码):
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var crypto = require('crypto');
var authTypes = ['github', 'twitter', 'facebook', 'google'];
var UserSchema = new Schema({
name: String,
email: { type: String, lowercase: true },
role: {
type: String,
default: 'user'
},
hashedPassword: String,
provider: String,
salt: String,
facebook: {},
google: {},
github: {}
});
/**
* Virtuals
*/
UserSchema
.virtual('password')
.set(function(password) {
this._password = password;
this.salt = this.makeSalt();
this.hashedPassword = this.encryptPassword(password);
})
.get(function() {
return this._password;
});
// Public profile information
UserSchema
.virtual('profile')
.get(function() {
return {
'name': this.name,
'role': this.role
};
});
// Non-sensitive info we'll be putting in the token
UserSchema
.virtual('token')
.get(function() {
return {
'_id': this._id,
'role': this.role
};
});
/**
* Validations
*/
// Validate empty email
UserSchema
.path('email')
.validate(function(email) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return email.length;
}, 'Email cannot be blank');
// Validate empty password
UserSchema
.path('hashedPassword')
.validate(function(hashedPassword) {
if (authTypes.indexOf(this.provider) !== -1) return true;
return hashedPassword.length;
}, 'Password cannot be blank');
// Validate email is not taken
UserSchema
.path('email')
.validate(function(value, respond) {
var self = this;
this.constructor.findOne({email: value}, function(err, user) {
if(err) throw err;
if(user) {
if(self.id === user.id) return respond(true);
return respond(false);
}
respond(true);
});
}, 'The specified email address is already in use.');
var validatePresenceOf = function(value) {
return value && value.length;
};
/**
* Pre-save hook
*/
UserSchema
.pre('save', function(next) {
if (!this.isNew) return next();
if (!validatePresenceOf(this.hashedPassword) && authTypes.indexOf(this.provider) === -1)
next(new Error('Invalid password'));
else
next();
});
/**
* Methods
*/
UserSchema.methods = {
/**
* Authenticate - check if the passwords are the same
*
* @param {String} plainText
* @return {Boolean}
* @api public
*/
authenticate: function(plainText) {
return this.encryptPassword(plainText) === this.hashedPassword;
},
/**
* Make salt
*
* @return {String}
* @api public
*/
makeSalt: function() {
return crypto.randomBytes(16).toString('base64');
},
/**
* Encrypt password
*
* @param {String} password
* @return {String}
* @api public
*/
encryptPassword: function(password) {
if (!password || !this.salt) return '';
var salt = new Buffer(this.salt, 'base64');
return crypto.pbkdf2Sync(password, salt, 10000, 64).toString('base64');
}
};
module.exports = mongoose.model('User', UserSchema);
我有一个控制器,它具有获取一个视频的功能 (exports.show) 和一个获取多个视频的功能 (exports.index),video.controller.js:
'use strict';
var _ = require('lodash');
var Video = require('./video.model');
// Get list of videos
exports.index = function(req, res) {
Video.find()
.populate('owner')
.exec(function (err, videos) {
console.log("Pulled videos:", videos);
if(err) { return handleError(res, err); }
return res.json(200, videos);
});
};
// Get a single video
exports.show = function(req, res) {
Video.findById(req.params.id)
.populate('owner')
.exec(function (err, video) {
if(err) { return handleError(res, err); }
if(!video) { return res.send(404); }
return res.json(video);
});
};
如果将视频添加到数据库并在重新启动服务器之前对其进行查询,则一切都会按预期运行。 populate 函数有效,每个视频都会填充一个 "owner"。一旦服务器重新启动,任何查询的所有所有者都是 null
,我不知道为什么。如果我查看 Mongo CLI 中的文档,视频有 "owner" 这是用户的字符串“_id”(这是预期的)。
> mongo
MongoDB shell version: 2.4.12
> db.videos.find()
{ "owner" : "550a11cb5b3bf655884fad40", "type" : "youtube", "name" : "test", "sourcemedia" : "xxxxxxx", "_id" : ObjectId("550a11d45b3bf655884fad41"), "date" : ISODate("2015-03-18T04:00:00Z"), "__v" : 0 }
我尝试使用 Schema.Type.ObjectId
作为视频 "owner" 的类型,但我得到了相同的结果:
owner : { type: Schema.Types.ObjectId, ref: 'User', required : true },
为什么我的视频的 "owner" 属性返回 null?
Mongo版本:2.4.12 Mongoose 版本:3.8.24
呸!使用 angular-fullstack 生成器,用户的 table 会在您每次重新启动服务器时自动重新播种。我的填充没有工作,因为每次重新启动时唯一用户 _id 都被擦除。
在 server/config/seed.js
中找到了这条评论,它告诉了我解决方案...
/**
* Populate DB with sample data on server start
* to disable, edit config/environment/index.js, and set `seedDB: false`
*/
为了解决我改变了server/config/environment/development.js
对象(对我来说在第8行)
seedDB: true
到
seedDB: false