在 angular-fullstack 中服务器重新启动后,Mongoose populate() 为空
Posted
技术标签:
【中文标题】在 angular-fullstack 中服务器重新启动后,Mongoose populate() 为空【英文标题】:Mongoose populate() is null after server restart in angular-fullstack 【发布时间】:2015-05-21 22:01:52 【问题描述】:我有引用“所有者”的“视频”猫鼬模式,该模式是对“用户”模式的引用。我正在使用 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);
);
;
如果将视频添加到数据库并在重新启动服务器之前进行查询,则一切都按预期运行。填充功能有效,并且为每个视频填充了一个“所有者”。服务器重新启动后,任何查询的所有所有者都是null
,我不知道为什么。如果我查看 Mongo CLI 中的文档,视频有“所有者”,它是用户的字符串“_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 : type: Schema.Types.ObjectId, ref: 'User', required : true ,
为什么我的视频的“所有者”属性返回 null?
Mongo 版本:2.4.12 猫鼬版本:3.8.24
【问题讨论】:
您有为用户注册的模型吗? 你可以试试owner : type: Schema.ObjectId, ref: 'User', required : true
【参考方案1】:
哇!使用 angular-fullstack 生成器,每次重新启动服务器时,用户的表都会自动重新播种。我的填充不起作用,因为每次我重新启动时唯一的用户 _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
【讨论】:
这似乎是 yeoman angular-fullstack 脚手架中的一个错误,为什么要开发和调试 volatile 用户(默认情况下应该设置为 false)。以上是关于在 angular-fullstack 中服务器重新启动后,Mongoose populate() 为空的主要内容,如果未能解决你的问题,请参考以下文章
最好用的在线财务软件“秒帐”——中服SaaS超市明星产品推荐
在 angular-fullstack 应用程序中更新后单个帖子不同步